Merge commit 'origin/master'

This commit is contained in:
sweinreuter
2012-04-11 10:29:06 +02:00
72 changed files with 2401 additions and 452 deletions
Binary file not shown.
Binary file not shown.
@@ -343,11 +343,12 @@ public class UnusedDeclarationInspection extends FilteringInspectionTool {
final RefElementImpl refElement = (RefElementImpl)refEntity;
if (!refElement.isSuspicious()) return;
final PsiElement element = refElement.getElement();
if (element == null) return;
PsiFile file = refElement.getContainingFile();
if (file == null) return;
final boolean isSuppressed = refElement.isSuppressed(getShortName());
if (!getContext().isToCheckMember(element, UnusedDeclarationInspection.this) || isSuppressed) {
if (isSuppressed || !scope.contains(element)) {
if (!getContext().isToCheckFile(file, UnusedDeclarationInspection.this) || isSuppressed) {
if (isSuppressed || !scope.contains(file)) {
getEntryPointsManager().addEntryPoint(refElement, false);
}
return;
@@ -372,6 +373,7 @@ public class UnusedDeclarationInspection extends FilteringInspectionTool {
@Override public void visitClass(RefClass aClass) {
final PsiClass psiClass = aClass.getElement();
if (psiClass == null) return;
if (
isAddAppletEnabled() && aClass.isApplet() ||
isAddServletEnabled() && aClass.isServlet()) {
@@ -118,7 +118,7 @@ public class TestIntegrationUtils {
public boolean includeMember(PsiMember member) {
if (!(member instanceof PsiMethod)) return false;
PsiModifierList list = member.getModifierList();
return list.hasModifierProperty(PsiModifier.PUBLIC);
return !list.hasModifierProperty(PsiModifier.PRIVATE);
}
}, false);
clazz = clazz.getSuperClass();
@@ -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.
@@ -30,31 +30,31 @@ import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.PsiSuperMethodImplUtil;
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
import com.intellij.psi.impl.java.stubs.PsiClassStub;
import com.intellij.psi.impl.source.ClassInnerStuffCache;
import com.intellij.psi.impl.source.Constants;
import com.intellij.psi.impl.source.PsiClassImpl;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.impl.source.*;
import com.intellij.psi.impl.source.tree.TreeElement;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.search.SearchScope;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
public class ClsClassImpl extends ClsRepositoryPsiElement<PsiClassStub<?>> implements PsiClass, PsiQualifiedNamedElement, Queryable {
public class ClsClassImpl extends ClsRepositoryPsiElement<PsiClassStub<?>> implements PsiExtensibleClass, PsiQualifiedNamedElement, Queryable {
public static final Key<PsiClass> DELEGATE_KEY = Key.create("DELEGATE");
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.compiled.ClsClassImpl");
private final ClassInnerStuffCache innersCache = new ClassInnerStuffCache(this);
private final ClassInnerStuffCache myInnersCache = new ClassInnerStuffCache(this);
private final PsiIdentifier myNameIdentifier;
private final PsiDocComment myDocComment;
public static final Key<PsiClass> DELEGATE_KEY = Key.create("DELEGATE");
public ClsClassImpl(final PsiClassStub stub) {
super(stub);
@@ -70,9 +70,9 @@ public class ClsClassImpl extends ClsRepositoryPsiElement<PsiClassStub<?>> imple
PsiModifierList modifierList = getModifierList();
PsiReferenceList extendsList = getExtendsList();
PsiReferenceList implementsList = getImplementsList();
PsiField[] fields = getFields();
PsiMethod[] methods = getMethods();
PsiClass[] classes = getInnerClasses();
List<PsiField> fields = getOwnFields();
List<PsiMethod> methods = getOwnMethods();
List<PsiClass> classes = getOwnInnerClasses();
int count =
(docComment != null ? 1 : 0)
@@ -80,9 +80,9 @@ public class ClsClassImpl extends ClsRepositoryPsiElement<PsiClassStub<?>> imple
+ 1 // name
+ 1 // extends list
+ 1 // implementsList
+ fields.length
+ methods.length
+ classes.length;
+ fields.size()
+ methods.size()
+ classes.size();
PsiElement[] children = new PsiElement[count];
int offset = 0;
@@ -95,12 +95,12 @@ public class ClsClassImpl extends ClsRepositoryPsiElement<PsiClassStub<?>> imple
children[offset++] = extendsList;
children[offset++] = implementsList;
System.arraycopy(fields, 0, children, offset, fields.length);
offset += fields.length;
System.arraycopy(methods, 0, children, offset, methods.length);
offset += methods.length;
System.arraycopy(classes, 0, children, offset, classes.length);
/*offset += classes.length;*/
ArrayUtil.copy(fields, children, offset);
offset += fields.size();
ArrayUtil.copy(methods, children, offset);
offset += methods.size();
ArrayUtil.copy(classes, children, offset);
/*offset += classes.size();*/
return children;
}
@@ -166,7 +166,6 @@ public class ClsClassImpl extends ClsRepositoryPsiElement<PsiClassStub<?>> imple
return getStub().findChildStubByType(JavaStubElementTypes.EXTENDS_LIST).getPsi();
}
@Override
@NotNull
public PsiReferenceList getImplementsList() {
@@ -222,25 +221,43 @@ public class ClsClassImpl extends ClsRepositoryPsiElement<PsiClassStub<?>> imple
@Override
@NotNull
public PsiField[] getFields() {
return getStub().getChildrenByType(Constants.FIELD_BIT_SET, PsiField.ARRAY_FACTORY);
return myInnersCache.getFields();
}
@Override
@NotNull
public PsiMethod[] getMethods() {
return getStub().getChildrenByType(Constants.METHOD_BIT_SET, PsiMethod.ARRAY_FACTORY);
return myInnersCache.getMethods();
}
@Override
@NotNull
public PsiMethod[] getConstructors() {
return PsiImplUtil.getConstructors(this);
return myInnersCache.getConstructors();
}
@Override
@NotNull
public PsiClass[] getInnerClasses() {
return getStub().getChildrenByType(JavaStubElementTypes.CLASS, ARRAY_FACTORY);
return myInnersCache.getInnerClasses();
}
@NotNull
@Override
public List<PsiField> getOwnFields() {
return Arrays.asList(getStub().getChildrenByType(Constants.FIELD_BIT_SET, PsiField.ARRAY_FACTORY));
}
@NotNull
@Override
public List<PsiMethod> getOwnMethods() {
return Arrays.asList(getStub().getChildrenByType(Constants.METHOD_BIT_SET, PsiMethod.ARRAY_FACTORY));
}
@NotNull
@Override
public List<PsiClass> getOwnInnerClasses() {
return Arrays.asList(getStub().getChildrenByType(JavaStubElementTypes.CLASS, ARRAY_FACTORY));
}
@Override
@@ -275,7 +292,7 @@ public class ClsClassImpl extends ClsRepositoryPsiElement<PsiClassStub<?>> imple
@Override
public PsiField findFieldByName(String name, boolean checkBases) {
return innersCache.findFieldByName(name, checkBases);
return myInnersCache.findFieldByName(name, checkBases);
}
@Override
@@ -292,7 +309,7 @@ public class ClsClassImpl extends ClsRepositoryPsiElement<PsiClassStub<?>> imple
@Override
@NotNull
public PsiMethod[] findMethodsByName(String name, boolean checkBases) {
return innersCache.findMethodsByName(name, checkBases);
return myInnersCache.findMethodsByName(name, checkBases);
}
@Override
@@ -309,7 +326,7 @@ public class ClsClassImpl extends ClsRepositoryPsiElement<PsiClassStub<?>> imple
@Override
public PsiClass findInnerClassByName(String name, boolean checkBases) {
return innersCache.findInnerClassByName(name, checkBases);
return myInnersCache.findInnerClassByName(name, checkBases);
}
@Override
@@ -386,50 +403,50 @@ public class ClsClassImpl extends ClsRepositoryPsiElement<PsiClassStub<?>> imple
}
buffer.append('{');
final int newIndentLevel = indentLevel + getIndentSize();
PsiField[] fields = getFields();
if (fields.length > 0) {
List<PsiField> fields = getOwnFields();
if (fields.size() > 0) {
goNextLine(newIndentLevel, buffer);
for (int i = 0; i < fields.length; i++) {
PsiField field = fields[i];
for (int i = 0; i < fields.size(); i++) {
PsiField field = fields.get(i);
((ClsElementImpl)field).appendMirrorText(newIndentLevel, buffer);
if (field instanceof ClsEnumConstantImpl) {
if (i < fields.length - 1 && fields[i + 1] instanceof ClsEnumConstantImpl) {
if (i < fields.size() - 1 && fields.get(i + 1) instanceof ClsEnumConstantImpl) {
buffer.append(", ");
}
else {
buffer.append(";");
if (i < fields.length - 1) {
if (i < fields.size() - 1) {
goNextLine(newIndentLevel, buffer);
}
}
} else if (i < fields.length - 1) {
} else if (i < fields.size() - 1) {
goNextLine(newIndentLevel, buffer);
}
}
}
PsiMethod[] methods = getMethods();
if (methods.length > 0) {
List<PsiMethod> methods = getOwnMethods();
if (methods.size() > 0) {
goNextLine(newIndentLevel, buffer);
goNextLine(newIndentLevel, buffer);
for (int i = 0; i < methods.length; i++) {
PsiMethod method = methods[i];
for (int i = 0; i < methods.size(); i++) {
PsiMethod method = methods.get(i);
((ClsElementImpl)method).appendMirrorText(newIndentLevel, buffer);
if (i < methods.length - 1) {
if (i < methods.size() - 1) {
goNextLine(newIndentLevel, buffer);
goNextLine(newIndentLevel, buffer);
}
}
}
PsiClass[] classes = getInnerClasses();
if (classes.length > 0) {
List<PsiClass> classes = getOwnInnerClasses();
if (classes.size() > 0) {
goNextLine(newIndentLevel, buffer);
goNextLine(newIndentLevel, buffer);
for (int i = 0; i < classes.length; i++) {
PsiClass aClass = classes[i];
for (int i = 0; i < classes.size(); i++) {
PsiClass aClass = classes.get(i);
((ClsElementImpl)aClass).appendMirrorText(newIndentLevel, buffer);
if (i < classes.length - 1) {
if (i < classes.size() - 1) {
goNextLine(newIndentLevel, buffer);
goNextLine(newIndentLevel, buffer);
}
@@ -459,37 +476,37 @@ public class ClsClassImpl extends ClsRepositoryPsiElement<PsiClassStub<?>> imple
Ref<Boolean> extLog = Ref.create(true);
PsiField[] fields = getFields();
List<PsiField> fields = getOwnFields();
PsiField[] mirrorFields = mirror.getFields();
if (fields.length == mirrorFields.length) {
for (int i = 0; i < fields.length; i++) {
((ClsElementImpl)fields[i]).setMirror(SourceTreeToPsiMap.psiToTreeNotNull(mirrorFields[i]));
if (fields.size() == mirrorFields.length) {
for (int i = 0; i < fields.size(); i++) {
((ClsElementImpl)fields.get(i)).setMirror(SourceTreeToPsiMap.psiToTreeNotNull(mirrorFields[i]));
}
}
else {
log(this, mirror, "fields:" + fields.length + "!=" + mirrorFields.length, extLog);
log(this, mirror, "fields:" + fields.size() + "!=" + mirrorFields.length, extLog);
}
PsiMethod[] methods = getMethods();
List<PsiMethod> methods = getOwnMethods();
PsiMethod[] mirrorMethods = mirror.getMethods();
if (methods.length == mirrorMethods.length) {
for (int i = 0; i < methods.length; i++) {
((ClsElementImpl)methods[i]).setMirror(SourceTreeToPsiMap.psiToTreeNotNull(mirrorMethods[i]));
if (methods.size() == mirrorMethods.length) {
for (int i = 0; i < methods.size(); i++) {
((ClsElementImpl)methods.get(i)).setMirror(SourceTreeToPsiMap.psiToTreeNotNull(mirrorMethods[i]));
}
}
else {
log(this, mirror, "methods:" + methods.length + "!=" + mirrorMethods.length, extLog);
log(this, mirror, "methods:" + methods.size() + "!=" + mirrorMethods.length, extLog);
}
PsiClass[] classes = getInnerClasses();
List<PsiClass> classes = getOwnInnerClasses();
PsiClass[] mirrorClasses = mirror.getInnerClasses();
if (classes.length == mirrorClasses.length) {
for (int i = 0; i < classes.length; i++) {
((ClsElementImpl)classes[i]).setMirror(SourceTreeToPsiMap.psiToTreeNotNull(mirrorClasses[i]));
if (classes.size() == mirrorClasses.length) {
for (int i = 0; i < classes.size(); i++) {
((ClsElementImpl)classes.get(i)).setMirror(SourceTreeToPsiMap.psiToTreeNotNull(mirrorClasses[i]));
}
}
else {
log(this, mirror, "classes:" + classes.length + "!=" + mirrorClasses.length, extLog);
log(this, mirror, "classes:" + classes.size() + "!=" + mirrorClasses.length, extLog);
}
}
@@ -628,5 +645,4 @@ public class ClsClassImpl extends ClsRepositoryPsiElement<PsiClassStub<?>> imple
protected boolean isVisibilitySupported() {
return true;
}
}
@@ -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.
@@ -37,7 +37,7 @@ import java.util.List;
import java.util.Map;
public class ClassInnerStuffCache {
private final PsiClass myClass;
private final PsiExtensibleClass myClass;
private final MyModificationTracker myTreeChangeTracker;
private CachedValue<PsiMethod[]> myConstructorsCache;
@@ -48,7 +48,7 @@ public class ClassInnerStuffCache {
private CachedValue<Map<String, List<PsiMethod>>> myMethodsMapCache;
private CachedValue<Map<String, PsiClass>> myInnerClassesMapCache;
public ClassInnerStuffCache(final PsiClass aClass) {
public ClassInnerStuffCache(final PsiExtensibleClass aClass) {
myClass = aClass;
myTreeChangeTracker = new MyModificationTracker();
}
@@ -197,27 +197,21 @@ public class ClassInnerStuffCache {
}
private PsiField[] getAllFields() {
if (!(myClass instanceof PsiClassImpl)) return myClass.getFields();
final PsiField[] own = ((PsiClassImpl)myClass).getStubOrPsiChildren(Constants.FIELD_BIT_SET, PsiField.ARRAY_FACTORY);
final List<PsiField> own = myClass.getOwnFields();
final List<PsiField> ext = PsiAugmentProvider.collectAugments(myClass, PsiField.class);
return ArrayUtil.mergeArrayAndCollection(own, ext, PsiField.ARRAY_FACTORY);
return ArrayUtil.mergeCollections(own, ext, PsiField.ARRAY_FACTORY);
}
private PsiMethod[] getAllMethods() {
if (!(myClass instanceof PsiClassImpl)) return myClass.getMethods();
final PsiMethod[] own = ((PsiClassImpl)myClass).getStubOrPsiChildren(Constants.METHOD_BIT_SET, PsiMethod.ARRAY_FACTORY);
final List<PsiMethod> own = myClass.getOwnMethods();
final List<PsiMethod> ext = PsiAugmentProvider.collectAugments(myClass, PsiMethod.class);
return ArrayUtil.mergeArrayAndCollection(own, ext, PsiMethod.ARRAY_FACTORY);
return ArrayUtil.mergeCollections(own, ext, PsiMethod.ARRAY_FACTORY);
}
private PsiClass[] getAllInnerClasses() {
if (!(myClass instanceof PsiClassImpl)) return myClass.getInnerClasses();
final PsiClass[] own = ((PsiClassImpl)myClass).getInnerClassesRaw();
final List<PsiClass> own = myClass.getOwnInnerClasses();
final List<PsiClass> ext = PsiAugmentProvider.collectAugments(myClass, PsiClass.class);
return ArrayUtil.mergeArrayAndCollection(own, ext, PsiClass.ARRAY_FACTORY);
return ArrayUtil.mergeCollections(own, ext, PsiClass.ARRAY_FACTORY);
}
@Nullable
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 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.
@@ -45,11 +45,12 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
public class PsiClassImpl extends JavaStubPsiElement<PsiClassStub<?>> implements PsiClass, PsiQualifiedNamedElement, Queryable {
public class PsiClassImpl extends JavaStubPsiElement<PsiClassStub<?>> implements PsiExtensibleClass, PsiQualifiedNamedElement, Queryable {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.PsiClassImpl");
private final ClassInnerStuffCache myInnersCache = new ClassInnerStuffCache(this);
@@ -75,7 +76,6 @@ public class PsiClassImpl extends JavaStubPsiElement<PsiClassStub<?>> implements
@Override
public void subtreeChanged() {
dropCaches();
super.subtreeChanged();
}
@@ -87,9 +87,7 @@ public class PsiClassImpl extends JavaStubPsiElement<PsiClassStub<?>> implements
@Override
protected Object clone() {
PsiClassImpl clone = (PsiClassImpl)super.clone();
clone.dropCaches();
return clone;
}
@@ -299,8 +297,21 @@ public class PsiClassImpl extends JavaStubPsiElement<PsiClassStub<?>> implements
}
@NotNull
public PsiClass[] getInnerClassesRaw() {
return getStubOrPsiChildren(JavaStubElementTypes.CLASS, ARRAY_FACTORY);
@Override
public List<PsiField> getOwnFields() {
return Arrays.asList(getStubOrPsiChildren(Constants.FIELD_BIT_SET, PsiField.ARRAY_FACTORY));
}
@NotNull
@Override
public List<PsiMethod> getOwnMethods() {
return Arrays.asList(getStubOrPsiChildren(Constants.METHOD_BIT_SET, PsiMethod.ARRAY_FACTORY));
}
@NotNull
@Override
public List<PsiClass> getOwnInnerClasses() {
return Arrays.asList(getStubOrPsiChildren(JavaStubElementTypes.CLASS, ARRAY_FACTORY));
}
@Override
@@ -577,6 +588,7 @@ public class PsiClassImpl extends JavaStubPsiElement<PsiClassStub<?>> implements
final StubElement parentStub = stub.getParentStub();
final StubBasedPsiElementBase<?> context = (StubBasedPsiElementBase)parentStub.getPsi();
@SuppressWarnings("unchecked")
PsiClass[] classesInScope = (PsiClass[])parentStub.getChildrenByType(Constants.CLASS_BIT_SET, ARRAY_FACTORY);
boolean needPreciseContext = false;
@@ -0,0 +1,34 @@
/*
* 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.psi.impl.source;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiMethod;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public interface PsiExtensibleClass extends PsiClass {
@NotNull
List<PsiField> getOwnFields();
@NotNull
List<PsiMethod> getOwnMethods();
@NotNull
List<PsiClass> getOwnInnerClasses();
}
@@ -0,0 +1,9 @@
Compiling files:
src/Util.java
End of files
Cleaning output files:
out/production/addClass/Client.class
End of files
Compiling files:
src/Client.java
End of files
@@ -0,0 +1 @@
addClass
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AntConfiguration">
<defaultAnt bundledAnt="true" />
</component>
</project>
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<option name="DEFAULT_COMPILER" value="Javac" />
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="?*.properties" />
<entry name="?*.xml" />
<entry name="?*.gif" />
<entry name="?*.png" />
<entry name="?*.jpeg" />
<entry name="?*.jpg" />
<entry name="?*.html" />
<entry name="?*.dtd" />
<entry name="?*.tld" />
<entry name="?*.ftl" />
</wildcardResourcePatterns>
<annotationProcessing enabled="false" useClasspath="true" />
</component>
</project>
@@ -0,0 +1,5 @@
<component name="CopyrightManager">
<settings default="">
<module2copyright />
</settings>
</component>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
</project>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="ProjectResources">
<default-html-doctype>http://www.w3.org/1999/xhtml</default-html-doctype>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="IDEA jdk" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/addClass.iml" filepath="$PROJECT_DIR$/addClass.iml" />
<module fileurl="file://$PROJECT_DIR$/common/common.iml" filepath="$PROJECT_DIR$/common/common.iml" />
</modules>
</component>
</project>
@@ -0,0 +1,5 @@
<component name="DependencyValidationManager">
<state>
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
</state>
</component>
@@ -0,0 +1,125 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="" />
</component>
</project>
@@ -0,0 +1,559 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="be875bae-1db2-477c-abf6-574af12c7ca3" name="Default" comment="" />
<ignored path="addClass.iws" />
<ignored path=".idea/workspace.xml" />
<option name="TRACKING_ENABLED" value="true" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ChangesViewManager" flattened_view="true" show_ignored="false" />
<component name="CreatePatchCommitExecutor">
<option name="PATCH_PATH" value="" />
</component>
<component name="DaemonCodeAnalyzer">
<disable_hints />
</component>
<component name="DebuggerManager">
<breakpoint_any>
<breakpoint>
<option name="NOTIFY_CAUGHT" value="true" />
<option name="NOTIFY_UNCAUGHT" value="true" />
<option name="ENABLED" value="false" />
<option name="LOG_ENABLED" value="false" />
<option name="LOG_EXPRESSION_ENABLED" value="false" />
<option name="SUSPEND_POLICY" value="SuspendAll" />
<option name="COUNT_FILTER_ENABLED" value="false" />
<option name="COUNT_FILTER" value="0" />
<option name="CONDITION_ENABLED" value="false" />
<option name="CLASS_FILTERS_ENABLED" value="false" />
<option name="INSTANCE_FILTERS_ENABLED" value="false" />
<option name="CONDITION" value="" />
<option name="LOG_MESSAGE" value="" />
</breakpoint>
<breakpoint>
<option name="NOTIFY_CAUGHT" value="true" />
<option name="NOTIFY_UNCAUGHT" value="true" />
<option name="ENABLED" value="false" />
<option name="LOG_ENABLED" value="false" />
<option name="LOG_EXPRESSION_ENABLED" value="false" />
<option name="SUSPEND_POLICY" value="SuspendAll" />
<option name="COUNT_FILTER_ENABLED" value="false" />
<option name="COUNT_FILTER" value="0" />
<option name="CONDITION_ENABLED" value="false" />
<option name="CLASS_FILTERS_ENABLED" value="false" />
<option name="INSTANCE_FILTERS_ENABLED" value="false" />
<option name="CONDITION" value="" />
<option name="LOG_MESSAGE" value="" />
</breakpoint>
</breakpoint_any>
<breakpoint_rules />
<ui_properties />
</component>
<component name="FavoritesManager">
<favorites_list name="addClass" />
</component>
<component name="FileEditorManager">
<leaf>
<file leaf-file-name="Util.java" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/common/src/Util.java">
<provider selected="true" editor-type-id="text-editor">
<state line="8" column="18" selection-start="187" selection-end="187" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="Client.java" pinned="false" current="true" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/src/Client.java">
<provider selected="true" editor-type-id="text-editor">
<state line="9" column="12" selection-start="189" selection-end="189" vertical-scroll-proportion="0.16605166">
<folding />
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="FindManager">
<FindUsagesManager>
<setting name="OPEN_NEW_TAB" value="false" />
</FindUsagesManager>
</component>
<component name="IdeDocumentHistory">
<option name="changedFiles">
<list>
<option value="$PROJECT_DIR$/common/src/Util.java" />
<option value="$PROJECT_DIR$/src/Client.java" />
<option value="$PROJECT_DIR$/src/Util.java" />
</list>
</option>
</component>
<component name="ProjectFrameBounds">
<option name="y" value="25" />
<option name="width" value="1280" />
<option name="height" value="974" />
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectReloadState">
<option name="STATE" value="0" />
</component>
<component name="ProjectView">
<navigator currentView="ProjectPane" proportions="" version="1" splitterProportion="0.5">
<flattenPackages />
<showMembers />
<showModules />
<showLibraryContents />
<hideEmptyPackages />
<abbreviatePackageNames />
<autoscrollToSource />
<autoscrollFromSource />
<sortByType />
</navigator>
<panes>
<pane id="Scope">
<subPane subId="Project Files">
<PATH>
<PATH_ELEMENT USER_OBJECT="Root">
<option name="myItemId" value="" />
<option name="myItemType" value="" />
</PATH_ELEMENT>
</PATH>
</subPane>
</pane>
<pane id="ProjectPane">
<subPane>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="addClass" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="addClass" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="addClass" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="addClass" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="addClass" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="src" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="addClass" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="addClass" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="common" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="addClass" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="addClass" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="common" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="src" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
</subPane>
</pane>
<pane id="PackagesPane" />
</panes>
</component>
<component name="PropertiesComponent">
<property name="GoToFile.includeJavaFiles" value="false" />
<property name="project.structure.last.edited" value="Modules" />
<property name="project.structure.proportion" value="0.0" />
<property name="options.splitter.main.proportions" value="0.3" />
<property name="MemberChooser.sorted" value="false" />
<property name="options.lastSelected" value="project.propCompiler" />
<property name="project.structure.side.proportion" value="0.0" />
<property name="MemberChooser.copyJavadoc" value="false" />
<property name="GoToClass.toSaveIncludeLibraries" value="false" />
<property name="MemberChooser.showClasses" value="true" />
<property name="GoToClass.includeLibraries" value="false" />
<property name="options.splitter.details.proportions" value="0.2" />
<property name="options.searchVisible" value="true" />
</component>
<component name="RunManager">
<configuration default="true" type="#org.jetbrains.idea.devkit.run.PluginConfigurationType" factoryName="Plugin">
<module name="" />
<option name="VM_PARAMETERS" value="-Xmx512m -Xms256m -XX:MaxPermSize=250m" />
<option name="PROGRAM_PARAMETERS" />
<method>
<option name="AntTarget" enabled="false" />
<option name="BuildArtifacts" enabled="false" />
<option name="Make" enabled="true" />
<option name="Maven.BeforeRunTask" enabled="false" />
</method>
</configuration>
<configuration default="true" type="Remote" factoryName="Remote">
<option name="USE_SOCKET_TRANSPORT" value="true" />
<option name="SERVER_MODE" value="false" />
<option name="SHMEM_ADDRESS" value="javadebug" />
<option name="HOST" value="localhost" />
<option name="PORT" value="5005" />
<method>
<option name="AntTarget" enabled="false" />
<option name="BuildArtifacts" enabled="false" />
<option name="Maven.BeforeRunTask" enabled="false" />
</method>
</configuration>
<configuration default="true" type="Applet" factoryName="Applet">
<module name="" />
<option name="MAIN_CLASS_NAME" />
<option name="HTML_FILE_NAME" />
<option name="HTML_USED" value="false" />
<option name="WIDTH" value="400" />
<option name="HEIGHT" value="300" />
<option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" />
<option name="VM_PARAMETERS" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<method>
<option name="AntTarget" enabled="false" />
<option name="BuildArtifacts" enabled="false" />
<option name="Make" enabled="true" />
<option name="Maven.BeforeRunTask" enabled="false" />
</method>
</configuration>
<configuration default="true" type="TestNG" factoryName="TestNG">
<module name="" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="SUITE_NAME" />
<option name="PACKAGE_NAME" />
<option name="MAIN_CLASS_NAME" />
<option name="METHOD_NAME" />
<option name="GROUP_NAME" />
<option name="TEST_OBJECT" value="CLASS" />
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="OUTPUT_DIRECTORY" />
<option name="ANNOTATION_TYPE" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="moduleWithDependencies" />
</option>
<option name="USE_DEFAULT_REPORTERS" value="false" />
<option name="PROPERTIES_FILE" />
<envs />
<properties />
<listeners />
<method>
<option name="AntTarget" enabled="false" />
<option name="BuildArtifacts" enabled="false" />
<option name="Make" enabled="true" />
<option name="Maven.BeforeRunTask" enabled="false" />
</method>
</configuration>
<configuration default="true" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" />
<option name="VM_PARAMETERS" />
<option name="PROGRAM_PARAMETERS" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="ENABLE_SWING_INSPECTOR" value="false" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<module name="" />
<envs />
<method>
<option name="AntTarget" enabled="false" />
<option name="BuildArtifacts" enabled="false" />
<option name="Make" enabled="true" />
<option name="Maven.BeforeRunTask" enabled="false" />
</method>
</configuration>
<configuration default="true" type="JUnit" factoryName="JUnit">
<module name="" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="PACKAGE_NAME" />
<option name="MAIN_CLASS_NAME" />
<option name="METHOD_NAME" />
<option name="TEST_OBJECT" value="class" />
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="moduleWithDependencies" />
</option>
<envs />
<patterns />
<method>
<option name="AntTarget" enabled="false" />
<option name="BuildArtifacts" enabled="false" />
<option name="Make" enabled="true" />
<option name="Maven.BeforeRunTask" enabled="false" />
</method>
</configuration>
<list size="0" />
<configuration name="&lt;template&gt;" type="WebApp" default="true" selected="false">
<Host>localhost</Host>
<Port>5050</Port>
</configuration>
</component>
<component name="ShelveChangesManager" show_recycled="false" />
<component name="SvnConfiguration" maxAnnotateRevisions="500" myUseAcceleration="nothing" myAutoUpdateAfterCommit="false" cleanupOnStartRun="false">
<option name="USER" value="" />
<option name="PASSWORD" value="" />
<option name="mySSHConnectionTimeout" value="30000" />
<option name="mySSHReadTimeout" value="30000" />
<option name="LAST_MERGED_REVISION" />
<option name="MERGE_DRY_RUN" value="false" />
<option name="MERGE_DIFF_USE_ANCESTRY" value="true" />
<option name="UPDATE_LOCK_ON_DEMAND" value="false" />
<option name="IGNORE_SPACES_IN_MERGE" value="false" />
<option name="DETECT_NESTED_COPIES" value="true" />
<option name="CHECK_NESTED_FOR_QUICK_MERGE" value="false" />
<option name="IGNORE_SPACES_IN_ANNOTATE" value="true" />
<option name="SHOW_MERGE_SOURCES_IN_ANNOTATE" value="true" />
<option name="FORCE_UPDATE" value="false" />
<configuration useDefault="false">$USER_HOME$/.subversion_IDEA</configuration>
<myIsUseDefaultProxy>false</myIsUseDefaultProxy>
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<created>1334130093404</created>
<updated>1334130093404</updated>
</task>
<servers />
</component>
<component name="ToolWindowManager">
<frame x="0" y="25" width="1280" height="974" extended-state="0" />
<editor active="false" />
<layout>
<window_info id="Changes" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="JetGradle" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Palette" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32897863" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="true" content_ui="tabs" />
<window_info id="Maven Projects" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Project" active="true" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.25" sideWeight="0.6710214" order="0" side_tool="false" content_ui="combo" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
</layout>
</component>
<component name="VcsContentAnnotationSettings">
<option name="myLimit" value="2678400000" />
</component>
<component name="VcsManagerConfiguration">
<option name="OFFER_MOVE_TO_ANOTHER_CHANGELIST_ON_PARTIAL_COMMIT" value="true" />
<option name="CHECK_CODE_SMELLS_BEFORE_PROJECT_COMMIT" value="true" />
<option name="CHECK_NEW_TODO" value="true" />
<option name="myTodoPanelSettings">
<value>
<are-packages-shown value="false" />
<are-modules-shown value="false" />
<flatten-packages value="false" />
<is-autoscroll-to-source value="false" />
</value>
</option>
<option name="PERFORM_UPDATE_IN_BACKGROUND" value="true" />
<option name="PERFORM_COMMIT_IN_BACKGROUND" value="true" />
<option name="PERFORM_EDIT_IN_BACKGROUND" value="true" />
<option name="PERFORM_CHECKOUT_IN_BACKGROUND" value="true" />
<option name="PERFORM_ADD_REMOVE_IN_BACKGROUND" value="true" />
<option name="PERFORM_ROLLBACK_IN_BACKGROUND" value="false" />
<option name="CHECK_LOCALLY_CHANGED_CONFLICTS_IN_BACKGROUND" value="false" />
<option name="ENABLE_BACKGROUND_PROCESSES" value="false" />
<option name="CHANGED_ON_SERVER_INTERVAL" value="60" />
<option name="SHOW_ONLY_CHANGED_IN_SELECTION_DIFF" value="true" />
<option name="CHECK_COMMIT_MESSAGE_SPELLING" value="true" />
<option name="DEFAULT_PATCH_EXTENSION" value="patch" />
<option name="SHORT_DIFF_HORISONTALLY" value="true" />
<option name="SHORT_DIFF_EXTRA_LINES" value="2" />
<option name="SOFT_WRAPS_IN_SHORT_DIFF" value="true" />
<option name="INCLUDE_TEXT_INTO_PATCH" value="false" />
<option name="INCLUDE_TEXT_INTO_SHELF" value="false" />
<option name="CREATE_PATCH_EXPAND_DETAILS_DEFAULT" value="true" />
<option name="SHOW_FILE_HISTORY_DETAILS" value="true" />
<option name="SHOW_VCS_ERROR_NOTIFICATIONS" value="true" />
<option name="FORCE_NON_EMPTY_COMMENT" value="false" />
<option name="CLEAR_INITIAL_COMMIT_MESSAGE" value="false" />
<option name="LAST_COMMIT_MESSAGE" />
<option name="MAKE_NEW_CHANGELIST_ACTIVE" value="false" />
<option name="OPTIMIZE_IMPORTS_BEFORE_PROJECT_COMMIT" value="false" />
<option name="CHECK_FILES_UP_TO_DATE_BEFORE_COMMIT" value="false" />
<option name="REFORMAT_BEFORE_PROJECT_COMMIT" value="false" />
<option name="REFORMAT_BEFORE_FILE_COMMIT" value="false" />
<option name="FILE_HISTORY_DIALOG_COMMENTS_SPLITTER_PROPORTION" value="0.8" />
<option name="FILE_HISTORY_DIALOG_SPLITTER_PROPORTION" value="0.5" />
<option name="ACTIVE_VCS_NAME" />
<option name="UPDATE_GROUP_BY_PACKAGES" value="false" />
<option name="UPDATE_GROUP_BY_CHANGELIST" value="false" />
<option name="SHOW_FILE_HISTORY_AS_TREE" value="false" />
<option name="FILE_HISTORY_SPLITTER_PROPORTION" value="0.6" />
</component>
<component name="XDebuggerManager">
<breakpoint-manager />
</component>
<component name="antWorkspaceConfiguration">
<option name="IS_AUTOSCROLL_TO_SOURCE" value="false" />
<option name="FILTER_TARGETS" value="false" />
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/common/src/Util.java">
<provider selected="true" editor-type-id="text-editor">
<state line="8" column="18" selection-start="187" selection-end="187" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Client.java">
<provider selected="true" editor-type-id="text-editor">
<state line="9" column="12" selection-start="189" selection-end="189" vertical-scroll-proportion="0.16605166">
<folding />
</state>
</provider>
</entry>
</component>
<component name="masterDetails">
<states>
<state key="ArtifactsStructureConfigurable.UI">
<settings>
<artifact-editor />
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
<state key="FacetStructureConfigurable.UI">
<settings>
<last-edited>No facets are configured</last-edited>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
<state key="GlobalLibrariesConfigurable.UI">
<settings>
<last-edited>Gant</last-edited>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
<state key="JdkListConfigurable.UI">
<settings>
<last-edited>IDEA jdk</last-edited>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
<state key="ModuleStructureConfigurable.UI">
<settings>
<last-edited>addClass</last-edited>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
<option value="0.5" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
<state key="ProjectJDKs.UI">
<settings>
<last-edited>IDEA jdk</last-edited>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.20000002" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
<state key="ProjectLibrariesConfigurable.UI">
<settings>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
</states>
</component>
</project>
@@ -0,0 +1,5 @@
public class Util {
public static void foo (int x) {
}
}
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="jdk" jdkName="IDEA jdk" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="common" />
</component>
</module>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
@@ -0,0 +1,12 @@
/**
* Created with IntelliJ IDEA.
* User: db
* Date: 11.04.12
* Time: 11:43
* To change this template use File | Settings | File Templates.
*/
public class Util {
public static void foo () {
}
}
@@ -0,0 +1,12 @@
/**
* Created with IntelliJ IDEA.
* User: db
* Date: 11.04.12
* Time: 11:43
* To change this template use File | Settings | File Templates.
*/
public class Client {
{
Util.foo();
}
}
@@ -77,6 +77,10 @@ public class CommonTest extends IncrementalTestCase {
}
public void testDeleteClass4() throws Exception {
doTest();
doTest();
}
public void testAddClass() throws Exception {
doTest();
}
}
+4 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2010 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.
@@ -24,6 +24,8 @@
// logging
void userlog(int priority, const char* format, ...);
#define CHECK_NULL(p, r) if (p == NULL) { userlog(LOG_ERR, "out of memory"); return r; }
// variable-length array
typedef struct __array array;
@@ -38,7 +40,7 @@ void array_delete(array* a);
void array_delete_vs_data(array* a);
// key/value pairs table
// poor man's hash table
typedef struct __table table;
table* table_create(int capacity);
+31 -21
View File
@@ -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.
@@ -32,8 +32,6 @@
#define DEFAULT_SUBDIR_COUNT 5
#define CHECK_NULL(p) if (p == NULL) { userlog(LOG_ERR, "out of memory"); return ERR_ABORT; }
typedef struct __watch_node {
char* name;
int wd;
@@ -153,9 +151,9 @@ static int add_watch(const char* path, watch_node* parent) {
node = malloc(sizeof(watch_node));
CHECK_NULL(node);
CHECK_NULL(node, ERR_ABORT);
node->name = strdup(path);
CHECK_NULL(node->name);
CHECK_NULL(node->name, ERR_ABORT);
node->wd = wd;
node->parent = parent;
node->kids = NULL;
@@ -163,9 +161,9 @@ static int add_watch(const char* path, watch_node* parent) {
if (parent != NULL) {
if (parent->kids == NULL) {
parent->kids = array_create(DEFAULT_SUBDIR_COUNT);
CHECK_NULL(parent->kids);
CHECK_NULL(parent->kids, ERR_ABORT);
}
CHECK_NULL(array_push(parent->kids, node));
CHECK_NULL(array_push(parent->kids, node), ERR_ABORT);
}
if (table_put(watches, wd, node) == NULL) {
@@ -238,25 +236,31 @@ static bool is_ignored(const char* path, array* ignores) {
return false;
}
static int walk_tree(const char* path, watch_node* parent, array* ignores) {
static int walk_tree(const char* path, watch_node* parent, array* ignores, bool recursive) {
if (is_ignored(path, ignores)) {
return ERR_IGNORE;
}
DIR* dir = opendir(path);
if (dir == NULL) {
if (errno == EACCES) {
return ERR_IGNORE;
DIR* dir;
if (recursive) {
dir = opendir(path);
if (dir == NULL) {
if (errno == EACCES) {
return ERR_IGNORE;
}
else if (errno == ENOTDIR) { // "future" root
return add_watch(path, parent);
}
userlog(LOG_ERR, "opendir(%s): %s", path, strerror(errno));
return ERR_CONTINUE;
}
else if (errno == ENOTDIR) { // flat root
return add_watch(path, parent);
}
userlog(LOG_ERR, "opendir(%s): %s", path, strerror(errno));
return ERR_CONTINUE;
}
int id = add_watch(path, parent);
if (id < 0) {
if (!recursive) {
return id;
}
else if (id < 0) {
closedir(dir);
return id;
}
@@ -279,7 +283,7 @@ static int walk_tree(const char* path, watch_node* parent, array* ignores) {
continue;
}
int subdir_id = walk_tree(subdir, table_get(watches, id), ignores);
int subdir_id = walk_tree(subdir, table_get(watches, id), ignores, recursive);
if (subdir_id < 0 && subdir_id != ERR_IGNORE) {
rm_watch(id, true);
id = subdir_id;
@@ -293,9 +297,15 @@ static int walk_tree(const char* path, watch_node* parent, array* ignores) {
int watch(const char* root, array* ignores) {
bool recursive = true;
if (root[0] == '|') {
root++;
recursive = false;
}
char buf[PATH_MAX];
const char* normalized = realpath(root, buf);
return walk_tree((normalized != NULL ? normalized : root), NULL, ignores);
return walk_tree((normalized != NULL ? normalized : root), NULL, ignores, recursive);
}
@@ -323,7 +333,7 @@ static bool process_inotify_event(struct inotify_event* event) {
}
if ((event->mask & IN_CREATE || event->mask & IN_MOVED_TO) && event->mask & IN_ISDIR) {
int result = walk_tree(path, node, NULL);
int result = walk_tree(path, node, NULL, true);
if (result < 0 && result != ERR_IGNORE) {
return false;
}
+9 -15
View File
@@ -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.
@@ -33,7 +33,7 @@
#define LOG_ENV_ERROR "error"
#define LOG_ENV_OFF "off"
#define VERSION "1.0"
#define VERSION "1.1"
#define VERSION_MSG "fsnotifier " VERSION "\n"
#define USAGE_MSG \
@@ -58,11 +58,8 @@ typedef struct {
static array* roots = NULL;
static bool show_warning = true;
static bool self_test = false;
#define CHECK_NULL(p) if (p == NULL) { userlog(LOG_ERR, "out of memory"); return false; }
static void init_log();
static void run_self_test();
static void main_loop();
@@ -223,7 +220,7 @@ static bool read_input() {
if (strcmp(line, "ROOTS") == 0) {
array* new_roots = array_create(20);
CHECK_NULL(new_roots);
CHECK_NULL(new_roots, false);
while (1) {
line = read_line(stdin);
@@ -235,12 +232,9 @@ static bool read_input() {
break;
}
else {
if (line[0] == '|') line++; // flat roots will be differentiated later
int l = strlen(line);
if (l > 1 && line[l-1] == '/') line[l-1] = '\0';
CHECK_NULL(array_push(new_roots, strdup(line)));
CHECK_NULL(array_push(new_roots, strdup(line)), false);
}
}
@@ -266,7 +260,7 @@ static bool update_roots(array* new_roots) {
}
array* unwatchable = array_create(20);
CHECK_NULL(unwatchable);
CHECK_NULL(unwatchable, false);
if (!unwatchable_mounts(unwatchable)) {
return false;
}
@@ -312,10 +306,10 @@ static bool register_roots(array* new_roots, array* unwatchable) {
}
else if (id >= 0) {
watch_root* root = malloc(sizeof(watch_root));
CHECK_NULL(root);
CHECK_NULL(root, false);
root->id = id;
root->name = new_root;
CHECK_NULL(array_push(roots, root));
CHECK_NULL(array_push(roots, root), false);
}
else {
if (show_warning && watch_limit_reached()) {
@@ -324,7 +318,7 @@ static bool register_roots(array* new_roots, array* unwatchable) {
output("MESSAGE\n" INOTIFY_LIMIT_MSG, limit);
show_warning = false; // warn only once
}
CHECK_NULL(array_push(unwatchable, new_root));
CHECK_NULL(array_push(unwatchable, new_root), false);
}
}
@@ -362,7 +356,7 @@ static bool unwatchable_mounts(array* mounts) {
}
if (!is_watchable(dev, point, fs)) {
CHECK_NULL(array_push(mounts, strdup(point)));
CHECK_NULL(array_push(mounts, strdup(point)), false);
}
}
@@ -25,4 +25,6 @@ import org.jetbrains.annotations.NotNull;
public abstract class LocalDummyInspectionTool extends LocalInspectionTool {
@NotNull
public abstract String getProblemGroup();
public abstract boolean shouldBeShownInInspectionProfile();
}
@@ -114,7 +114,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
private volatile boolean allowToInterrupt = true;
private StatusBarUpdater myStatusBarUpdater;
public DaemonCodeAnalyzerImpl(Project project, DaemonCodeAnalyzerSettings daemonCodeAnalyzerSettings, EditorTracker editorTracker) {
public DaemonCodeAnalyzerImpl(@NotNull Project project, DaemonCodeAnalyzerSettings daemonCodeAnalyzerSettings, EditorTracker editorTracker) {
myProject = project;
mySettings = daemonCodeAnalyzerSettings;
@@ -125,7 +125,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
myPassExecutorService = new PassExecutorService(myProject) {
@Override
protected void afterApplyInformationToEditor(final TextEditorHighlightingPass pass,
final FileEditor fileEditor,
@NotNull final FileEditor fileEditor,
final ProgressIndicator updateProgress) {
if (fileEditor instanceof TextEditor) {
log(updateProgress, pass, "Apply ");
@@ -143,19 +143,20 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
Disposer.register(project, myFileStatusMap);
}
static boolean hasErrors(Project project, Document document) {
static boolean hasErrors(@NotNull Project project, @NotNull Document document) {
return !processHighlights(document, project, HighlightSeverity.ERROR, 0, document.getTextLength(), CommonProcessors.<HighlightInfo>alwaysFalse());
}
@NotNull
@TestOnly
public static List<HighlightInfo> getHighlights(Document document, HighlightSeverity minSeverity, Project project) {
public static List<HighlightInfo> getHighlights(@NotNull Document document, HighlightSeverity minSeverity, @NotNull Project project) {
List<HighlightInfo> infos = new ArrayList<HighlightInfo>();
processHighlights(document, project, minSeverity, 0, document.getTextLength(),
new CommonProcessors.CollectProcessor<HighlightInfo>(infos));
return infos;
}
@NotNull
public List<HighlightInfo> runMainPasses(@NotNull PsiFile psiFile,
@NotNull Document document,
@NotNull final ProgressIndicator progress) {
@@ -184,6 +185,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
return result;
}
@NotNull
@TestOnly
public List<HighlightInfo> runPasses(@NotNull PsiFile file,
@NotNull Document document,
@@ -326,7 +328,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
myLastSettings = null;
}
void repaintErrorStripeRenderer(Editor editor) {
void repaintErrorStripeRenderer(@NotNull Editor editor) {
if (!myProject.isInitialized()) return;
final Document document = editor.getDocument();
final PsiFile psiFile = PsiDocumentManager.getInstance(myProject).getPsiFile(document);
@@ -349,7 +351,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
dependencyValidationManager.reloadRules();
}
private static void addScopesToList(final List<Pair<NamedScope, NamedScopesHolder>> scopeList, final NamedScopesHolder holder) {
private static void addScopesToList(@NotNull final List<Pair<NamedScope, NamedScopesHolder>> scopeList, @NotNull final NamedScopesHolder holder) {
NamedScope[] scopes = holder.getScopes();
for (NamedScope scope : scopes) {
scopeList.add(Pair.create(scope, holder));
@@ -416,7 +418,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
}
@Override
public boolean isHighlightingAvailable(PsiFile file) {
public boolean isHighlightingAvailable(@Nullable PsiFile file) {
if (file == null || !file.isPhysical()) return false;
if (myDisabledHighlightingFiles.contains(PsiUtilCore.getVirtualFile(file))) return false;
@@ -453,6 +455,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
stopProcess(true);
}
@NotNull
public List<TextEditorHighlightingPass> getPassesToShowProgressFor(Document document) {
List<TextEditorHighlightingPass> allPasses = myPassExecutorService.getAllSubmittedPasses();
List<TextEditorHighlightingPass> result = new ArrayList<TextEditorHighlightingPass>(allPasses.size());
@@ -472,7 +475,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
myFileStatusMap.allDirtyScopesAreNull(document);
}
public boolean isErrorAnalyzingFinished(PsiFile file) {
public boolean isErrorAnalyzingFinished(@NotNull PsiFile file) {
if (myDisposed) return false;
Document document = PsiDocumentManager.getInstance(myProject).getCachedDocument(file);
return document != null &&
@@ -480,6 +483,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
myFileStatusMap.getFileDirtyScope(document, Pass.UPDATE_ALL) == null;
}
@NotNull
public FileStatusMap getFileStatusMap() {
return myFileStatusMap;
}
@@ -526,7 +530,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
MarkupModelEx model = (MarkupModelEx)DocumentMarkupModel.forDocument(document, project, true);
return model.processRangeHighlightersOverlappingWith(startOffset, endOffset, new Processor<RangeHighlighterEx>() {
@Override
public boolean process(RangeHighlighterEx marker) {
public boolean process(@NotNull RangeHighlighterEx marker) {
Object tt = marker.getErrorStripeTooltip();
if (!(tt instanceof HighlightInfo)) return true;
HighlightInfo info = (HighlightInfo)tt;
@@ -549,7 +553,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
MarkupModelEx model = (MarkupModelEx)DocumentMarkupModel.forDocument(document, project, true);
return model.processRangeHighlightersOutside(startOffset, endOffset, new Processor<RangeHighlighterEx>() {
@Override
public boolean process(RangeHighlighterEx marker) {
public boolean process(@NotNull RangeHighlighterEx marker) {
Object tt = marker.getErrorStripeTooltip();
if (!(tt instanceof HighlightInfo)) return true;
HighlightInfo info = (HighlightInfo)tt;
@@ -569,7 +573,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
@NotNull final Processor<HighlightInfo> processor) {
return processHighlights(document, project, null, 0, document.getTextLength(), new Processor<HighlightInfo>() {
@Override
public boolean process(HighlightInfo info) {
public boolean process(@NotNull HighlightInfo info) {
if (!isOffsetInsideHighlightInfo(offset, info, includeFixRange)) return true;
int compare = info.getSeverity().compareTo(minSeverity);
@@ -579,11 +583,11 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
}
@Nullable
public HighlightInfo findHighlightByOffset(Document document, final int offset, final boolean includeFixRange) {
public HighlightInfo findHighlightByOffset(@NotNull Document document, final int offset, final boolean includeFixRange) {
final List<HighlightInfo> foundInfoList = new SmartList<HighlightInfo>();
processHighlightsNearOffset(document, myProject, HighlightSeverity.INFORMATION, offset, includeFixRange, new Processor<HighlightInfo>() {
@Override
public boolean process(HighlightInfo info) {
public boolean process(@NotNull HighlightInfo info) {
if (!foundInfoList.isEmpty()) {
HighlightInfo foundInfo = foundInfoList.get(0);
int compare = foundInfo.getSeverity().compareTo(info.getSeverity());
@@ -604,7 +608,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
return new HighlightInfoComposite(foundInfoList);
}
private static boolean isOffsetInsideHighlightInfo(int offset, HighlightInfo info, boolean includeFixRange) {
private static boolean isOffsetInsideHighlightInfo(int offset, @NotNull HighlightInfo info, boolean includeFixRange) {
RangeHighlighterEx highlighter = info.highlighter;
if (highlighter == null || !highlighter.isValid()) return false;
int startOffset = highlighter.getStartOffset();
@@ -624,7 +628,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
}
@Nullable
public static List<LineMarkerInfo> getLineMarkers(Document document, Project project) {
public static List<LineMarkerInfo> getLineMarkers(@NotNull Document document, Project project) {
ApplicationManager.getApplication().assertIsDispatchThread();
MarkupModel markup = DocumentMarkupModel.forDocument(document, project, true);
return markup.getUserData(MARKERS_IN_EDITOR_DOCUMENT_KEY);
@@ -636,7 +640,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
markup.putUserData(MARKERS_IN_EDITOR_DOCUMENT_KEY, lineMarkers);
}
public synchronized void setLastIntentionHint(Project project, PsiFile file, Editor editor, ShowIntentionsPass.IntentionsInfo intentions, boolean hasToRecreate) {
public synchronized void setLastIntentionHint(@NotNull Project project, @NotNull PsiFile file, @NotNull Editor editor, @NotNull ShowIntentionsPass.IntentionsInfo intentions, boolean hasToRecreate) {
ApplicationManager.getApplication().assertIsDispatchThread();
hideLastIntentionHint();
IntentionHintComponent hintComponent = IntentionHintComponent.showIntentionHint(project, file, editor, intentions, false);
@@ -653,12 +657,13 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
}
}
@Nullable
public synchronized IntentionHintComponent getLastIntentionHint() {
return myLastIntentionHint;
}
@Override
public void writeExternal(Element parentNode) throws WriteExternalException {
public void writeExternal(@NotNull Element parentNode) throws WriteExternalException {
Element disableHintsElement = new Element(DISABLE_HINTS_TAG);
parentNode.addContent(disableHintsElement);
@@ -678,7 +683,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
}
@Override
public void readExternal(Element parentNode) throws InvalidDataException {
public void readExternal(@NotNull Element parentNode) throws InvalidDataException {
myDisabledHintsFiles.clear();
Element element = parentNode.getChild(DISABLE_HINTS_TAG);
@@ -697,6 +702,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
}
}
@NotNull
private Runnable createUpdateRunnable() {
return new Runnable() {
@Override
@@ -754,6 +760,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
};
}
@NotNull
private synchronized DaemonProgressIndicator createUpdateProgress() {
DaemonProgressIndicator progress = new DaemonProgressIndicator() {
@Override
@@ -767,7 +774,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
return progress;
}
public boolean canChangeFileSilently(PsiFileSystemItem file) {
public boolean canChangeFileSilently(@NotNull PsiFileSystemItem file) {
return myDaemonListeners.canChangeFileSilently(file);
}
@@ -780,7 +787,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
@NotNull
@TestOnly
public static List<HighlightInfo> getFileLevelHighlights(Project project,PsiFile file ) {
public static List<HighlightInfo> getFileLevelHighlights(@NotNull Project project, @NotNull PsiFile file ) {
return UpdateHighlightersUtil.getFileLeveleHighlights(project, file);
}
@@ -148,20 +148,20 @@ class DaemonListeners implements Disposable {
@Override
public void activeEditorsChanged(@NotNull List<Editor> editors) {
List<Editor> activeEditors = getActiveEditors();
if (!myActiveEditors.equals(activeEditors)) {
myActiveEditors = activeEditors;
stopDaemon(true); // do not stop daemon if idea loses/gains focus
if (LaterInvocator.isInModalContext()) {
// editor appear in modal context, reenable the daemon
myDaemonCodeAnalyzer.setUpdateByTimerEnabled(true);
}
myDaemonCodeAnalyzer.hideLastIntentionHint(); // mem leak after closing last editor otherwise
if (myActiveEditors.equals(activeEditors)) {
return;
}
myActiveEditors = activeEditors;
stopDaemon(true); // do not stop daemon if idea loses/gains focus
if (LaterInvocator.isInModalContext()) {
// editor appear in modal context, re-enable the daemon
myDaemonCodeAnalyzer.setUpdateByTimerEnabled(true);
}
}
};
myEditorTracker.addEditorTrackerListener(editorTrackerListener, this);
EditorFactoryListener editorFactoryListener = new EditorFactoryAdapter() {
EditorFactoryListener editorFactoryListener = new EditorFactoryListener() {
@Override
public void editorCreated(@NotNull EditorFactoryEvent event) {
Editor editor = event.getEditor();
@@ -175,6 +175,12 @@ class DaemonListeners implements Disposable {
}
myDaemonCodeAnalyzer.repaintErrorStripeRenderer(editor);
}
@Override
public void editorReleased(@NotNull EditorFactoryEvent event) {
// mem leak after closing last editor otherwise
myDaemonCodeAnalyzer.hideLastIntentionHint();
}
};
EditorFactory.getInstance().addEditorFactoryListener(editorFactoryListener, this);
@@ -19,6 +19,7 @@ package com.intellij.codeInspection.ex;
import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.intellij.codeInspection.LocalDummyInspectionTool;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.psi.search.scope.packageSet.NamedScope;
@@ -43,6 +44,7 @@ public class Descriptor {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ex.Descriptor");
private final ScopeToolState myState;
private final InspectionProfileImpl myInspectionProfile;
private boolean myShouldBeShown = true;
public Descriptor(ScopeToolState pair, InspectionProfileImpl inspectionProfile) {
myState = pair;
@@ -56,6 +58,14 @@ public class Descriptor {
myEnabled = ((InspectionProfileImpl)inspectionProfile).isToolEnabled(myKey, pair.getScope());
myTool = tool;
myScope = pair.getScope();
if (tool instanceof InspectionToolWrapper) {
InspectionProfileEntry inspection = ((InspectionToolWrapper)tool).getTool();
if (inspection instanceof LocalDummyInspectionTool) {
myShouldBeShown = ((LocalDummyInspectionTool)inspection).shouldBeShownInInspectionProfile();
}
}
}
public boolean equals(Object obj) {
@@ -80,6 +90,10 @@ public class Descriptor {
myEnabled = enabled;
}
public boolean shouldBeShown() {
return myShouldBeShown;
}
public String getText() {
return myText;
}
@@ -71,7 +71,10 @@ import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class GlobalInspectionContextImpl extends UserDataHolderBase implements GlobalInspectionContext {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ex.GlobalInspectionContextImpl");
@@ -346,16 +349,15 @@ public class GlobalInspectionContextImpl extends UserDataHolderBase implements G
public boolean isToCheckMember(@NotNull RefElement owner, InspectionProfileEntry tool) {
final PsiElement element = owner.getElement();
return isToCheckMember(element, tool) && !((RefElementImpl)owner).isSuppressed(tool.getShortName());
return isToCheckFile(((RefElementImpl)owner).getContainingFile(), tool) && !((RefElementImpl)owner).isSuppressed(tool.getShortName());
}
public boolean isToCheckMember(final PsiElement element, final InspectionProfileEntry tool) {
public boolean isToCheckFile(PsiFile file, final InspectionProfileEntry tool) {
final Tools tools = myTools.get(tool.getShortName());
if (tools != null) {
for (ScopeToolState state : tools.getTools()) {
final NamedScope namedScope = state.getScope(element.getProject());
if (namedScope == null || namedScope.getValue().contains(element.getContainingFile(), getCurrentProfile().getProfileManager().getScopesManager())) {
final NamedScope namedScope = state.getScope(file.getProject());
if (namedScope == null || namedScope.getValue().contains(file, getCurrentProfile().getProfileManager().getScopesManager())) {
if (state.isEnabled()) {
final InspectionProfileEntry entry = state.getTool();
if (entry instanceof InspectionToolWrapper && ((InspectionToolWrapper)entry).getTool() == tool) return true;
@@ -19,10 +19,7 @@ package com.intellij.codeInspection.ex;
import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInsight.daemon.InspectionProfileConvertor;
import com.intellij.codeInspection.InspectionProfile;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.ModifiableModel;
import com.intellij.codeInspection.*;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
@@ -58,7 +58,8 @@ public class ProjectInspectionToolsConfigurable extends InspectionToolsConfigura
@Override
public boolean isModified() {
if (!Comparing.strEqual(getCurrentProfile().getName(), getSelectedObject().getName())) return true;
final InspectionProfileImpl selectedObject = getSelectedObject();
if (selectedObject != null && !Comparing.strEqual(getCurrentProfile().getName(), selectedObject.getName())) return true;
return super.isModified();
}
}
@@ -21,14 +21,8 @@ import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInsight.daemon.impl.SeverityRegistrar;
import com.intellij.codeInspection.InspectionProfile;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.ModifiableModel;
import com.intellij.codeInspection.ex.Descriptor;
import com.intellij.codeInspection.ex.InspectionProfileImpl;
import com.intellij.codeInspection.ex.InspectionToolRegistrar;
import com.intellij.codeInspection.ex.ScopeToolState;
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.ex.*;
import com.intellij.ide.CommonActionsManager;
import com.intellij.ide.DefaultTreeExpander;
import com.intellij.ide.IdeTooltipManager;
@@ -685,7 +679,7 @@ public class SingleInspectionProfilePanel extends JPanel {
keySetList.addAll(SearchUtil.findKeys(filter, quated));
}
for (Descriptor descriptor : myDescriptors.keySet()) {
if (filter != null && filter.length() > 0 && !isDescriptorAccepted(descriptor, filter, forceInclude, keySetList, quated)) {
if (!descriptor.shouldBeShown() || filter != null && filter.length() > 0 && !isDescriptorAccepted(descriptor, filter, forceInclude, keySetList, quated)) {
continue;
}
final List<ScopeToolState> nonDefaultTools = mySelectedProfile.getNonDefaultTools(descriptor.getKey().toString());
@@ -173,6 +173,7 @@ public abstract class BaseRefactoringProcessor {
}
catch (Throwable e) {
anyException.set(Boolean.TRUE);
LOG.error(e);
}
}
};
@@ -203,7 +203,7 @@ public class RenameUtil {
});
}
public static void doRenameGenericNamedElement(PsiElement namedElement, String newName, UsageInfo[] usages,
public static void doRenameGenericNamedElement(@NotNull PsiElement namedElement, String newName, UsageInfo[] usages,
@Nullable RefactoringElementListener listener) throws IncorrectOperationException {
PsiWritableMetaData writableMetaData = null;
if (namedElement instanceof PsiMetaOwner) {
@@ -213,7 +213,7 @@ public class RenameUtil {
}
}
if (writableMetaData == null && !(namedElement instanceof PsiNamedElement)) {
LOG.error("Unknown element type");
LOG.error("Unknown element type:" + namedElement);
}
boolean hasBindables = false;
@@ -21,9 +21,11 @@ import org.jetbrains.annotations.NotNull;
* @author max
*/
public abstract class EditorFactoryAdapter implements EditorFactoryListener {
@Override
public void editorCreated(@NotNull EditorFactoryEvent event) {
}
@Override
public void editorReleased(@NotNull EditorFactoryEvent event) {
}
}
@@ -20,34 +20,32 @@ import com.intellij.notification.Notification;
import com.intellij.notification.NotificationListener;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileSystemUtil;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.ManagingFS;
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
import com.intellij.openapi.vfs.watcher.ChangeKind;
import com.intellij.util.PairFunction;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import javax.swing.event.HyperlinkEvent;
import java.io.*;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author max
*/
public class FileWatcher {
@NonNls public static final String PROPERTY_WATCHER_DISABLED = "filewatcher.disabled";
@NonNls private static final String PROPERTY_WATCHER_EXECUTABLE_PATH = "idea.filewatcher.executable.path";
@NonNls public static final String PROPERTY_WATCHER_DISABLED = "idea.filewatcher.disabled";
@NonNls public static final String PROPERTY_WATCHER_EXECUTABLE_PATH = "idea.filewatcher.executable.path";
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.impl.local.FileWatcher");
@@ -59,15 +57,7 @@ public class FileWatcher {
@NonNls private static final String EXIT_COMMAND = "EXIT";
@NonNls private static final String MESSAGE_COMMAND = "MESSAGE";
private static final PairFunction<String,String,Boolean> PATH_COMPARATOR = new PairFunction<String, String, Boolean>() {
@Override
public Boolean fun(final String s1, final String s2) {
return SystemInfo.isFileSystemCaseSensitive ? s1.equals(s2) : s1.equalsIgnoreCase(s2);
}
};
private final Object LOCK = new Object();
private final Lock SET_ROOTS_LOCK = new ReentrantLock(true);
private List<String> myDirtyPaths = new ArrayList<String>();
private List<String> myDirtyRecursivePaths = new ArrayList<String>();
@@ -75,21 +65,23 @@ public class FileWatcher {
private List<String> myManualWatchRoots = new ArrayList<String>();
private final List<Pair<String, String>> myMapping = new ArrayList<Pair<String, String>>();
private List<Pair<String, String>> myCanonicalMapping = new ArrayList<Pair<String, String>>();
private List<String> myRecursiveWatchRoots = new ArrayList<String>();
private List<String> myFlatWatchRoots = new ArrayList<String>();
private final Collection<String> myAllPaths = new ArrayList<String>(2);
private final Collection<String> myWatchedPaths = new ArrayList<String>(2);
private File executable;
private volatile Process notifierProcess;
private volatile BufferedReader notifierReader;
private volatile BufferedWriter notifierWriter;
private volatile BufferedWriter notifierWriter;
private boolean myFailureShownToTheUser = false;
private int attemptCount = 0;
private static final int MAX_PROCESS_LAUNCH_ATTEMPT_COUNT = 10;
private boolean isShuttingDown = false;
private final ManagingFS myManagingFS;
private final ManagingFS myManagingFS;
private static final FileWatcher ourInstance = new FileWatcher();
public static FileWatcher getInstance() {
@@ -140,7 +132,6 @@ public class FileWatcher {
myDirtyRecursivePaths = new ArrayList<String>();
return result;
}
}
public List<String> getDirtyDirs() {
@@ -158,26 +149,16 @@ public class FileWatcher {
}
public void setWatchRoots(final List<String> recursive, final List<String> flat) {
SET_ROOTS_LOCK.lock();
try {
synchronized (LOCK) {
if (myRecursiveWatchRoots.equals(recursive) && myFlatWatchRoots.equals(flat)) return;
}
final List<Pair<String, String>> mapping = new ArrayList<Pair<String, String>>();
long t = System.nanoTime();
final List<String> checkedRecursive = checkPaths(recursive, mapping);
final List<String> checkedFlat = checkPaths(flat, mapping);
t = (System.nanoTime() - t) / 1000;
LOG.info((recursive.size() + flat.size()) + " paths checked, " + mapping.size() + " mapped, " + t + " mks");
synchronized (LOCK) {
if (myRecursiveWatchRoots.equals(recursive) && myFlatWatchRoots.equals(flat)) return;
if (isAlive()) {
try {
writeLine(ROOTS_COMMAND);
for (String path : checkedRecursive) {
for (String path : recursive) {
writeLine(path);
}
for (String path : checkedFlat) {
for (String path : flat) {
writeLine("|" + path);
}
writeLine("#");
@@ -187,37 +168,10 @@ public class FileWatcher {
}
}
synchronized (LOCK) {
myRecursiveWatchRoots = recursive;
myFlatWatchRoots = flat;
myMapping.clear();
myCanonicalMapping = mapping;
}
myRecursiveWatchRoots = recursive;
myFlatWatchRoots = flat;
myMapping.clear();
}
finally {
SET_ROOTS_LOCK.unlock();
}
}
private static List<String> checkPaths(final List<String> paths, final List<Pair<String, String>> mapping) {
if (!SystemInfo.areSymLinksSupported) return paths;
final List<String> checkedPaths = new ArrayList<String>(paths.size());
for (String path : paths) {
String watched = path;
final String canonical = getCanonicalPath(path);
//noinspection ConstantConditions
if (!PATH_COMPARATOR.fun(path, canonical)) {
mapping.add(Pair.create((watched = canonical), path));
}
checkedPaths.add(watched);
}
return checkedPaths;
}
private static String getCanonicalPath(final String path) {
final String realPath = FileSystemUtil.resolveSymLink(path);
return realPath != null ? realPath : path;
}
private boolean isAlive() {
@@ -247,43 +201,34 @@ public class FileWatcher {
shutdownProcess();
String execPath = null;
if (executable == null) {
executable = getExecutable();
final String altExecPath = System.getProperty(PROPERTY_WATCHER_EXECUTABLE_PATH);
if (altExecPath != null && new File(altExecPath).isFile()) {
execPath = FileUtil.toSystemDependentName(altExecPath);
}
if (execPath == null) {
final String execName;
execName = getExecutableName();
if (execName == null) {
if (executable == null) {
myFailureShownToTheUser = true; // ignore unsupported platforms
return;
}
execPath = PathManager.getBinPath() + File.separatorChar + execName;
if (!executable.exists()) {
notifyOnFailure("File watcher is not found at path: " + executable, null);
return;
}
if (!executable.canExecute()) {
final String message = "File watcher is not executable: <a href=\"" + executable + "\">" + executable + "</a>";
final File exec = executable;
notifyOnFailure(message, new NotificationListener() {
@Override
public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
ShowFilePathAction.openFile(exec);
}
});
return;
}
}
final File exec = new File(execPath);
if (!exec.exists()) {
notifyOnFailure("File watcher is not found at path: " + execPath, null);
return;
}
if (!exec.canExecute()) {
notifyOnFailure("File watcher is not executable: <a href=\"" + execPath + "\">" + execPath +"</a>", new NotificationListener() {
@Override
public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
ShowFilePathAction.openFile(exec);
}
});
return;
}
LOG.info("Starting file watcher: " + execPath);
notifierProcess = Runtime.getRuntime().exec(new String[]{execPath});
LOG.info("Starting file watcher: " + executable);
notifierProcess = Runtime.getRuntime().exec(executable.getAbsolutePath());
notifierReader = new BufferedReader(new InputStreamReader(notifierProcess.getInputStream()));
notifierWriter = new BufferedWriter(new OutputStreamWriter(notifierProcess.getOutputStream()));
@@ -299,15 +244,43 @@ public class FileWatcher {
}
@Nullable
private static String getExecutableName() {
private static File getExecutable() {
String execPath = null;
final String altExecPath = System.getProperty(PROPERTY_WATCHER_EXECUTABLE_PATH);
if (altExecPath != null && new File(altExecPath).isFile()) {
execPath = FileUtil.toSystemDependentName(altExecPath);
}
if (execPath == null) {
final String execName = getExecutableName(false);
if (execName == null) {
return null;
}
execPath = FileUtil.join(PathManager.getBinPath(), execName);
}
File exec = new File(execPath);
if (!exec.exists()) {
String homePath = PathManager.getHomePath();
if (new File(homePath, "community").exists()) {
homePath += File.separator + "community";
}
exec = new File(FileUtil.join(homePath, "bin", getExecutableName(true)));
}
return exec;
}
@Nullable
private static String getExecutableName(final boolean withSubDir) {
if (SystemInfo.isWindows) {
return "fsnotifier.exe";
return (withSubDir ? "win" + File.separator : "") + "fsnotifier.exe";
}
else if (SystemInfo.isMac) {
return "fsnotifier";
return (withSubDir ? "mac" + File.separator : "") + "fsnotifier";
}
else if (SystemInfo.isLinux) {
return SystemInfo.isAMD64 ? "fsnotifier64" : "fsnotifier";
return (withSubDir ? "linux" + File.separator : "") + (SystemInfo.isAMD64 ? "fsnotifier64" : "fsnotifier");
}
return null;
@@ -316,7 +289,8 @@ public class FileWatcher {
private void notifyOnFailure(String cause, @Nullable NotificationListener listener) {
if (!myFailureShownToTheUser) {
myFailureShownToTheUser = true;
Notifications.Bus.notify(new Notification(Notifications.SYSTEM_MESSAGES_GROUP_ID, "External file sync may be slow", cause, NotificationType.WARNING, listener));
Notifications.Bus.notify(new Notification(Notifications.SYSTEM_MESSAGES_GROUP_ID, "External file sync may be slow",
cause, NotificationType.WARNING, listener));
}
}
@@ -339,6 +313,32 @@ public class FileWatcher {
return notifierProcess != null;
}
@TestOnly
public void startup() throws IOException {
final Application app = ApplicationManager.getApplication();
assert app != null && app.isUnitTestMode() : app;
myFailureShownToTheUser = true;
attemptCount = 0;
startupProcess(false);
attemptCount = 2 * MAX_PROCESS_LAUNCH_ATTEMPT_COUNT;
if (notifierProcess != null) {
new WatchForChangesThread().start();
}
}
@TestOnly
public void shutdown() throws InterruptedException {
final Application app = ApplicationManager.getApplication();
assert app != null && app.isUnitTestMode() : app;
final Process process = notifierProcess;
if (process != null) {
shutdownProcess();
process.waitFor();
}
}
private class WatchForChangesThread extends Thread {
public WatchForChangesThread() {
//noinspection HardCodedStringLiteral
@@ -396,7 +396,7 @@ public class FileWatcher {
final String pathB = readLine();
if (pathB == null || "#".equals(pathB)) break;
pairs.add(new Pair<String, String>(ensureEndsWithSlash(pathA), ensureEndsWithSlash(pathB)));
pairs.add(Pair.create(preparePathForMapping(pathA), preparePathForMapping(pathB)));
}
while (true);
@@ -414,10 +414,10 @@ public class FileWatcher {
}
synchronized (LOCK) {
final String watchedPath = checkWatchable(path);
if (watchedPath != null) {
final Collection<String> watchedPaths = checkWatchable(path);
if (!watchedPaths.isEmpty()) {
try {
onPathChange(ChangeKind.valueOf(command), watchedPath);
onPathChange(ChangeKind.valueOf(command), watchedPaths);
}
catch (IllegalArgumentException e) {
LOG.error("Illegal watcher command: " + command);
@@ -438,9 +438,9 @@ public class FileWatcher {
}
}
private static String ensureEndsWithSlash(String path) {
if (path.endsWith("/") || path.endsWith(File.separator)) return path;
return path + '/';
private static String preparePathForMapping(final String path) {
final String localPath = FileUtil.toSystemDependentName(path);
return localPath.endsWith(File.separator) ? localPath : localPath + File.separator;
}
private void writeLine(String line) throws IOException {
@@ -486,64 +486,76 @@ public class FileWatcher {
return line;
}
public boolean isWatched(VirtualFile file) {
return isOperational() && checkWatchable(file.getPresentableUrl()) != null;
public boolean isWatched(@NotNull final VirtualFile file) {
if (isOperational()) {
synchronized (LOCK) {
return !checkWatchable(file.getPresentableUrl()).isEmpty();
}
}
return false;
}
@Nullable
private String checkWatchable(String path) {
if (path == null) return null;
@NotNull
private Collection<String> checkWatchable(final String reportedPath) {
if (reportedPath == null) return Collections.emptyList();
for (Pair<String, String> mapping : myCanonicalMapping) {
if (path.startsWith(mapping.first)) {
path = mapping.second + path.substring(mapping.first.length());
break;
myAllPaths.clear();
myAllPaths.add(reportedPath);
for (Pair<String, String> map : myMapping) {
if (FileUtil.startsWith(reportedPath, map.first)) {
myAllPaths.add(map.second + reportedPath.substring(map.first.length()));
}
else if (FileUtil.startsWith(reportedPath, map.second)) {
myAllPaths.add(map.first + reportedPath.substring(map.second.length()));
}
}
for (String root : myRecursiveWatchRoots) {
if (FileUtil.startsWith(path, root)) {
return path;
myWatchedPaths.clear();
ext:
for (String path : myAllPaths) {
for (String root : myRecursiveWatchRoots) {
if (FileUtil.startsWith(path, root)) {
myWatchedPaths.add(path);
continue ext;
}
}
for (String root : myFlatWatchRoots) {
if (FileUtil.pathsEqual(path, root)) {
myWatchedPaths.add(path);
continue ext;
}
final File parentFile = new File(path).getParentFile();
if (parentFile != null && FileUtil.pathsEqual(parentFile.getPath(), root)) {
myWatchedPaths.add(path);
continue ext;
}
}
}
for (String root : myFlatWatchRoots) {
if (FileUtil.pathsEqual(path, root)) {
return path;
}
final File parentFile = new File(path).getParentFile();
if (parentFile != null && FileUtil.pathsEqual(parentFile.getPath(), root)) {
return path;
}
}
return null;
return myWatchedPaths;
}
private void onPathChange(final ChangeKind changeKind, final String path) {
private void onPathChange(final ChangeKind changeKind, final Collection<String> paths) {
switch (changeKind) {
case STATS:
case CHANGE:
addPath(path, myDirtyPaths);
myDirtyPaths.addAll(paths);
break;
case CREATE:
case DELETE:
final File parentFile = new File(path).getParentFile();
if (parentFile != null) {
addPath(parentFile.getPath(), myDirtyPaths);
}
else {
addPath(path, myDirtyPaths);
for (String path : paths) {
final File parent = new File(path).getParentFile();
myDirtyPaths.add(parent != null ? parent.getPath() : path);
}
break;
case DIRTY:
addPath(path, myDirtyDirs);
myDirtyDirs.addAll(paths);
break;
case RECDIRTY:
addPath(path, myDirtyRecursivePaths);
myDirtyRecursivePaths.addAll(paths);
break;
case RESET:
@@ -552,19 +564,6 @@ public class FileWatcher {
}
}
private void addPath(String path, List<String> list) {
list.add(path);
for (Pair<String, String> map : myMapping) {
if (FileUtil.startsWith(path, map.getFirst())) {
list.add(map.getSecond() + path.substring(map.getFirst().length()));
}
else if (FileUtil.startsWith(path, map.getSecond())) {
list.add(map.getFirst() + path.substring(map.getSecond().length()));
}
}
}
private void reset() {
synchronized (LOCK) {
myDirtyPaths.clear();
@@ -0,0 +1,438 @@
/*
* 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.openapi.vfs.local;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.idea.Bombed;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.*;
import com.intellij.openapi.vfs.impl.local.FileWatcher;
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent;
import com.intellij.openapi.vfs.newvfs.events.VFileCreateEvent;
import com.intellij.openapi.vfs.newvfs.events.VFileDeleteEvent;
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
import com.intellij.testFramework.PlatformLangTestCase;
import com.intellij.util.Function;
import com.intellij.util.TimeoutUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.messages.MessageBusConnection;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.*;
public class FileWatcherTest extends PlatformLangTestCase {
private static final int NATIVE_PROCESS_DELAY = 500; // time to event to be caught by native watcher and passed to watcher thread
private FileWatcher myWatcher;
private LocalFileSystem myFileSystem;
private MessageBusConnection myConnection;
private final List<VFileEvent> myEvents = new ArrayList<VFileEvent>();
@Override
protected void setUp() throws Exception {
super.setUp();
myWatcher = FileWatcher.getInstance();
assertNotNull(myWatcher);
assertFalse(myWatcher.isOperational());
myWatcher.startup();
assertTrue(myWatcher.isOperational());
myFileSystem = LocalFileSystem.getInstance();
assertNotNull(myFileSystem);
myConnection = ApplicationManager.getApplication().getMessageBus().connect();
myConnection.subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() {
@Override
public void before(@NotNull List<? extends VFileEvent> events) {
}
@Override
public void after(@NotNull List<? extends VFileEvent> events) {
synchronized (myEvents) {
myEvents.addAll(events);
myEvents.notifyAll();
}
}
});
}
@Override
protected void tearDown() throws Exception {
try {
myConnection.disconnect();
myWatcher.shutdown();
}
finally {
myFileSystem = null;
myWatcher = null;
super.tearDown();
}
}
public void testFileRoot() throws Exception {
final File file = FileUtil.createTempFile("test.", ".txt");
refresh(file);
final LocalFileSystem.WatchRequest request = watch(file);
try {
FileUtil.writeToFile(file, "new content");
assertEvent(VFileContentChangeEvent.class, file.getAbsolutePath());
FileUtil.delete(file);
assertEvent(VFileDeleteEvent.class, file.getAbsolutePath());
FileUtil.writeToFile(file, "re-creation");
assertEvent(VFileCreateEvent.class, file.getAbsolutePath());
}
finally {
myFileSystem.removeWatchedRoot(request);
FileUtil.delete(file);
}
}
public void testNonCanonicallyNamedFileRoot() throws Exception {
if (SystemInfo.isFileSystemCaseSensitive) {
System.out.println("Ignored: case-insensitive FS required");
return;
}
final File file = FileUtil.createTempFile("test.", ".txt");
refresh(file);
final String watchRoot = file.getAbsolutePath().toUpperCase(Locale.US);
final LocalFileSystem.WatchRequest request = watch(new File(watchRoot));
try {
FileUtil.writeToFile(file, "new content");
assertEvent(VFileContentChangeEvent.class, file.getAbsolutePath());
FileUtil.delete(file);
assertEvent(VFileDeleteEvent.class, file.getAbsolutePath());
FileUtil.writeToFile(file, "re-creation");
assertEvent(VFileCreateEvent.class, file.getAbsolutePath());
}
finally {
myFileSystem.removeWatchedRoot(request);
FileUtil.delete(file);
}
}
public void testDirectoryRecursive() throws Exception {
final File topDir = FileUtil.createTempDirectory("top.", null);
refresh(topDir);
final LocalFileSystem.WatchRequest request = watch(topDir);
try {
final File subDir = FileUtil.createTempDirectory(topDir, "sub.", null);
assertEvent(VFileCreateEvent.class, subDir.getAbsolutePath());
refresh(subDir);
final File file = FileUtil.createTempFile(subDir, "test.", ".txt", true, false);
assertEvent(VFileCreateEvent.class, file.getAbsolutePath());
FileUtil.writeToFile(file, "new content");
assertEvent(VFileContentChangeEvent.class, file.getAbsolutePath());
FileUtil.delete(file);
assertEvent(VFileDeleteEvent.class, file.getAbsolutePath());
FileUtil.writeToFile(file, "re-creation");
assertEvent(VFileCreateEvent.class, file.getAbsolutePath());
}
finally {
myFileSystem.removeWatchedRoot(request);
FileUtil.delete(topDir);
}
}
public void testDirectoryFlat() throws Exception {
final File topDir = FileUtil.createTempDirectory("top.", null);
final File watchedFile = FileUtil.createTempFile(topDir, "test.", ".txt", true, false);
final File subDir = FileUtil.createTempDirectory(topDir, "sub.", null);
final File unwatchedFile = FileUtil.createTempFile(subDir, "test.", ".txt", true, false);
refresh(topDir);
final LocalFileSystem.WatchRequest request = watch(topDir, false);
try {
FileUtil.writeToFile(watchedFile, "new content");
assertEvent(VFileContentChangeEvent.class, watchedFile.getAbsolutePath());
FileUtil.writeToFile(unwatchedFile, "new content");
assertEvent(VFileEvent.class);
}
finally {
myFileSystem.removeWatchedRoot(request);
FileUtil.delete(topDir);
}
}
public void testDirectoryNonExisting() throws Exception {
final File topDir = FileUtil.createTempDirectory("top.", null);
final File subDir = new File(topDir, "subDir");
final File file = new File(subDir, "file.txt");
refresh(topDir);
final LocalFileSystem.WatchRequest request = watch(subDir);
try {
assertTrue(subDir.toString(), subDir.mkdir());
assertEvent(VFileCreateEvent.class, subDir.getAbsolutePath());
refresh(subDir);
FileUtil.writeToFile(file, "new content");
assertEvent(VFileCreateEvent.class, file.getAbsolutePath());
}
finally {
myFileSystem.removeWatchedRoot(request);
FileUtil.delete(topDir);
}
}
public void testDirectoryOverlapping() throws Exception {
final File topDir = FileUtil.createTempDirectory("top.", null);
final File file1 = FileUtil.createTempFile(topDir, "file1.", ".txt", true, false);
final File subDir = FileUtil.createTempDirectory(topDir, "sub.", null);
final File file2 = FileUtil.createTempFile(subDir, "file2.", ".txt", true, false);
final File sideDir = FileUtil.createTempDirectory("side.", null);
final File file3 = FileUtil.createTempFile(sideDir, "file3.", ".txt", true, false);
refresh(topDir);
refresh(sideDir);
final LocalFileSystem.WatchRequest request1 = watch(subDir);
final LocalFileSystem.WatchRequest request2 = watch(sideDir);
try {
FileUtil.writeToFile(file1, "new content");
FileUtil.writeToFile(file2, "new content");
FileUtil.writeToFile(file3, "new content");
assertEvent(VFileContentChangeEvent.class, file2.getAbsolutePath(), file3.getAbsolutePath());
final LocalFileSystem.WatchRequest request3 = watch(topDir);
try {
FileUtil.writeToFile(file1, "newer content");
FileUtil.writeToFile(file2, "newer content");
FileUtil.writeToFile(file3, "newer content");
assertEvent(VFileContentChangeEvent.class, file1.getAbsolutePath(), file2.getAbsolutePath(), file3.getAbsolutePath());
}
finally {
unwatch(request3);
}
FileUtil.writeToFile(file1, "newest content");
FileUtil.writeToFile(file2, "newest content");
FileUtil.writeToFile(file3, "newest content");
assertEvent(VFileContentChangeEvent.class, file2.getAbsolutePath(), file3.getAbsolutePath());
FileUtil.delete(file1);
FileUtil.delete(file2);
FileUtil.delete(file3);
assertEvent(VFileDeleteEvent.class, file1.getAbsolutePath(), file2.getAbsolutePath(), file3.getAbsolutePath());
}
finally {
myFileSystem.removeWatchedRoots(Arrays.asList(request1, request2));
FileUtil.delete(topDir);
}
}
@Bombed(user = "roman.shevchenko", year = 2012, month = Calendar.MAY, day = 1)
public void testSymlinkAboveWatchRoot() throws Exception {
final File topDir = FileUtil.createTempDirectory("top.", null);
final File topLink = SymlinkHandlingTest.createTempLink(topDir.getAbsolutePath(), "link");
final File subDir = FileUtil.createTempDirectory(topDir, "sub.", null);
final File file = FileUtil.createTempFile(subDir, "test.", ".txt", true, false);
final File fileLink = new File(new File(topLink, subDir.getName()), file.getName());
refresh(topDir);
refresh(topLink);
final LocalFileSystem.WatchRequest request = watch(topLink);
try {
FileUtil.writeToFile(file, "new content");
assertEvent(VFileContentChangeEvent.class, fileLink.getAbsolutePath());
FileUtil.delete(file);
assertEvent(VFileDeleteEvent.class, fileLink.getAbsolutePath());
FileUtil.writeToFile(file, "re-creation");
assertEvent(VFileCreateEvent.class, fileLink.getAbsolutePath());
}
finally {
myFileSystem.removeWatchedRoot(request);
FileUtil.delete(topLink);
FileUtil.delete(topDir);
}
}
@Bombed(user = "roman.shevchenko", year = 2012, month = Calendar.MAY, day = 1)
public void testSymlinkBelowWatchRoot() throws Exception {
final File targetDir = FileUtil.createTempDirectory("top.", null);
final File file = FileUtil.createTempFile(targetDir, "test.", ".txt", true, false);
final File linkDir = FileUtil.createTempDirectory("link.", null);
final File link = new File(linkDir, "link");
SymlinkHandlingTest.createTempLink(targetDir.getAbsolutePath(), link.getAbsolutePath());
final File fileLink = new File(link, file.getName());
refresh(targetDir);
refresh(linkDir);
final LocalFileSystem.WatchRequest request = watch(linkDir);
try {
FileUtil.writeToFile(file, "new content");
assertEvent(VFileContentChangeEvent.class, fileLink.getAbsolutePath());
FileUtil.delete(file);
assertEvent(VFileDeleteEvent.class, fileLink.getAbsolutePath());
FileUtil.writeToFile(file, "re-creation");
assertEvent(VFileCreateEvent.class, fileLink.getAbsolutePath());
}
finally {
myFileSystem.removeWatchedRoot(request);
FileUtil.delete(linkDir);
FileUtil.delete(targetDir);
}
}
public void testSubst() throws Exception {
if (!SystemInfo.isWindows) {
System.out.println("Ignored: Windows required");
return;
}
final Set<Character> roots = ContainerUtil.map2Set(File.listRoots(), new Function<File, Character>() {
@Override
public Character fun(File root) {
return root.getPath().toLowerCase(Locale.US).charAt(0);
}
});
char subst = 0;
for (char c = 'e'; c <= 'z'; c++) {
if (!roots.contains(c)) {
subst = c;
break;
}
}
assertFalse("Occupied: " + roots.toString(), subst == 0);
final File targetDir = FileUtil.createTempDirectory("top.", null);
final File subDir = FileUtil.createTempDirectory(targetDir, "sub.", null);
final File file = FileUtil.createTempFile(subDir, "test.", ".txt", true, false);
final int rv = new GeneralCommandLine("subst", subst + ":", targetDir.getAbsolutePath()).createProcess().waitFor();
assertEquals(0, rv);
final File substDir = new File((subst + ":\\").toUpperCase(Locale.US), subDir.getName());
final File substFile = new File(substDir, file.getName());
refresh(targetDir);
refresh(substDir);
final LocalFileSystem.WatchRequest request = watch(substDir);
try {
FileUtil.writeToFile(file, "new content");
assertEvent(VFileContentChangeEvent.class, substFile.getAbsolutePath());
final LocalFileSystem.WatchRequest request2 = watch(targetDir);
try {
FileUtil.delete(file);
assertEvent(VFileDeleteEvent.class, file.getAbsolutePath(), substFile.getAbsolutePath());
}
finally {
unwatch(request2);
}
FileUtil.writeToFile(file, "re-creation");
assertEvent(VFileCreateEvent.class, substFile.getAbsolutePath());
}
finally {
myFileSystem.removeWatchedRoot(request);
new GeneralCommandLine("subst", subst + ":", "/d").createProcess().waitFor();
FileUtil.delete(targetDir);
}
}
private List<VFileEvent> getEvents() throws InterruptedException {
TimeoutUtil.sleep(NATIVE_PROCESS_DELAY);
myFileSystem.refresh(false);
synchronized (myEvents) {
final ArrayList<VFileEvent> result = new ArrayList<VFileEvent>(myEvents);
myEvents.clear();
return result;
}
}
private void clearEvents() {
myFileSystem.refresh(false);
synchronized (myEvents) {
myEvents.clear();
}
}
@NotNull
private LocalFileSystem.WatchRequest watch(final File watchFile) throws InterruptedException {
return watch(watchFile, true);
}
@NotNull
private LocalFileSystem.WatchRequest watch(final File watchFile, final boolean recursive) throws InterruptedException {
final LocalFileSystem.WatchRequest request = myFileSystem.addRootToWatch(watchFile.getAbsolutePath(), recursive);
assertNotNull(request);
TimeoutUtil.sleep(NATIVE_PROCESS_DELAY);
clearEvents();
return request;
}
private void unwatch(final LocalFileSystem.WatchRequest request) throws InterruptedException {
myFileSystem.removeWatchedRoot(request);
TimeoutUtil.sleep(NATIVE_PROCESS_DELAY);
clearEvents();
}
private VirtualFile refresh(final File file) {
final VirtualFile vFile = myFileSystem.refreshAndFindFileByIoFile(file);
assertNotNull(file.toString(), vFile);
VfsUtilCore.visitChildrenRecursively(vFile, new VirtualFileVisitor() {
@Override
public boolean visitFile(@NotNull VirtualFile file) {
file.getChildren();
return true;
}
});
return vFile;
}
private void assertEvent(final Class<? extends VFileEvent> type, final String... paths) throws InterruptedException {
final List<VFileEvent> events = getEvents();
assertEquals(events.toString(), paths.length, events.size());
final Set<String> pathSet = ContainerUtil.map2Set(paths, new Function<String, String>() {
@Override
public String fun(final String path) {
return FileUtil.toSystemIndependentName(path);
}
});
for (final VFileEvent event : events) {
assertTrue(event.toString(), type.isInstance(event));
final VirtualFile eventFile = event.getFile();
assertNotNull(event.toString(), eventFile);
assertTrue(eventFile + " not in " + Arrays.toString(paths), pathSet.remove(eventFile.getPath()));
}
}
}
@@ -266,7 +266,7 @@ public class SymlinkHandlingTest extends LightPlatformLangTestCase {
}
// todo[r.sh] use NIO2 API after migration to JDK 7
private static File createTempLink(final String target, final String link) throws InterruptedException, ExecutionException {
public static File createTempLink(final String target, final String link) throws InterruptedException, ExecutionException {
final boolean isAbsolute = SystemInfo.isUnix && StringUtil.startsWithChar(link, '/') ||
SystemInfo.isWindows && link.matches("^[c-zC-Z]:[/\\\\].*$");
final File linkFile = isAbsolute ? new File(link) : new File(FileUtil.getTempDirectory(), link);
@@ -648,13 +648,16 @@ public class ArrayUtil extends ArrayUtilRt {
return indexOf(objects, o) >= 0;
}
@NotNull
public static int[] newIntArray(int count) {
return count == 0 ? EMPTY_INT_ARRAY : new int[count];
}
@NotNull
public static String[] newStringArray(int count) {
return count == 0 ? EMPTY_STRING_ARRAY : new String[count];
}
@NotNull
public static Object[] newObjectArray(int count) {
return count == 0 ? EMPTY_OBJECT_ARRAY : new Object[count];
@@ -664,7 +667,9 @@ public class ArrayUtil extends ArrayUtilRt {
public static <E> E[] ensureExactSize(int count, @NotNull E[] sample) {
if (count == sample.length) return sample;
return (E[])Array.newInstance(sample.getClass().getComponentType(), count);
@SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
final E[] array = (E[])Array.newInstance(sample.getClass().getComponentType(), count);
return array;
}
@Nullable
@@ -677,13 +682,15 @@ public class ArrayUtil extends ArrayUtilRt {
return array.length > 0 ? array[array.length - 1] : null;
}
/** @deprecated use {@linkplain #mergeArrays(Object[], Object[])} (to remove in IDEA 12) */
public static <T> T[] join(T[] array1, T[] array2) {
return mergeArrays(array1, array2);
}
@NotNull
public static String[] toStringArray(@NotNull Collection<String> collection) {
return ArrayUtilRt.toStringArray(collection);
}
public static <T> void copy(@NotNull final Collection<? extends T> src, @NotNull final T[] dst, final int dstOffset) {
int i = dstOffset;
for (T t : src) {
dst[i++] = t;
}
}
}
@@ -20,11 +20,12 @@ import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.FilePathImpl;
import com.intellij.openapi.vcs.VcsRoot;
import org.jetbrains.annotations.NonNls;
public class FilePathUnderVcs {
private final FilePath myPath;
private final AbstractVcs myVcs;
private int hashcode;
private int hashCode;
public FilePathUnderVcs(final FilePath path, final AbstractVcs vcs) {
myPath = path;
@@ -59,13 +60,15 @@ public class FilePathUnderVcs {
@Override
public int hashCode() {
if (hashcode == 0) {
hashcode = myPath != null ? myPath.hashCode() : 0;
hashcode = 31 * hashcode + (myVcs != null ? myVcs.getName().hashCode() : 0);
if (hashCode == 0) {
int hc = myPath != null ? myPath.hashCode() : 0;
hc = 31 * hc + (myVcs != null ? myVcs.getName().hashCode() : 0);
hashCode = hc;
}
return hashcode;
return hashCode;
}
@NonNls
@Override
public String toString() {
return "FilePathUnderVcs{" +
@@ -164,6 +164,10 @@ class UpdatingChangeListBuilder implements ChangelistBuilder {
checkIfDisposed();
if (isExcluded(file)) return;
if (myScope.belongsTo(new FilePathImpl(file))) {
if (ChangeListManagerImpl.DEBUG) {
System.out.println("UpdatingChangeListBuilder.processModifiedWithoutCheckout");
System.out.println("file = " + file);
}
myComposite.getVFHolder(FileHolder.HolderType.MODIFIED_WITHOUT_EDITING).addFile(file);
}
}
@@ -0,0 +1,46 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.android.designer.designSurface.layout;
import com.intellij.android.designer.designSurface.AbstractEditOperation;
import com.intellij.android.designer.model.RadViewComponent;
import com.intellij.designer.designSurface.OperationContext;
/**
* @author Alexander Lobas
*/
public class AbsoluteLayoutOperation extends AbstractEditOperation {
public AbsoluteLayoutOperation(RadViewComponent container, OperationContext context) {
super(container, context);
}
@Override
public void showFeedback() {
// TODO: Auto-generated method stub
}
@Override
public void eraseFeedback() {
// TODO: Auto-generated method stub
}
@Override
public void execute() throws Exception {
if (!myContext.isMove()) {
super.execute();
}
}
}
@@ -43,11 +43,11 @@ import java.util.List;
public class LayoutMarginOperation implements EditOperation {
public static final String TYPE = "layout_margin";
private final OperationContext myContext;
private RadViewComponent myComponent;
private RectangleFeedback myFeedback;
private TextFeedback myTextFeedback;
private Rectangle myMargins;
protected final OperationContext myContext;
protected RadViewComponent myComponent;
protected RectangleFeedback myFeedback;
protected TextFeedback myTextFeedback;
protected Rectangle myMargins;
public LayoutMarginOperation(OperationContext context) {
myContext = context;
@@ -71,13 +71,17 @@ public class LayoutMarginOperation implements EditOperation {
myTextFeedback.setBorder(new LineMarginBorder(0, 5, 3, 0));
layer.add(myTextFeedback);
myFeedback = new RectangleFeedback(Color.orange, 2);
myFeedback = new RectangleFeedback(getFeedbackColor(), 2);
layer.add(myFeedback);
layer.repaint();
}
}
protected Color getFeedbackColor() {
return Color.orange;
}
@Override
public void showFeedback() {
createFeedback();
@@ -86,17 +90,20 @@ public class LayoutMarginOperation implements EditOperation {
applyMargins(bounds, myMargins);
myFeedback.setBounds(bounds);
myTextFeedback.clear();
fillTextFeedback();
myTextFeedback.locationTo(myContext.getLocation(), 15);
}
protected void fillTextFeedback() {
Point moveDelta = myContext.getMoveDelta();
Dimension sizeDelta = myContext.getSizeDelta();
int direction = myContext.getResizeDirection();
myTextFeedback.clear();
if (direction == Position.WEST) { // left
myTextFeedback.append(Integer.toString(myMargins.x - moveDelta.x));
}
else if (direction == Position.EAST) { // right
myTextFeedback.append(Integer.toString(myMargins.width + sizeDelta.width));
}
else if (direction == Position.NORTH) { // top
@@ -107,7 +114,6 @@ public class LayoutMarginOperation implements EditOperation {
}
myTextFeedback.dimension("dp");
myTextFeedback.locationTo(myContext.getLocation(), 15);
}
@Override
@@ -181,11 +187,42 @@ public class LayoutMarginOperation implements EditOperation {
}
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// ResizePoint
//
//////////////////////////////////////////////////////////////////////////////////////////
private static final BasicStroke STROKE = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1, new float[]{1, 2}, 0);
public static void points(ResizeSelectionDecorator decorator) {
decorator.addPoint(new ResizePoint() {
pointFeedback(decorator);
decorator.addPoint(new DirectionResizePoint(Color.orange, Color.black, Position.WEST, TYPE) { // left
@Override
protected Point getLocation(DecorationLayer layer, RadComponent component) {
Point location = super.getLocation(layer, component);
location.x -= ((RadViewComponent)component).getMargins().x;
return location;
}
});
pointRight(decorator, Color.orange, 0.25, TYPE);
decorator.addPoint(new DirectionResizePoint(Color.orange, Color.black, Position.NORTH, TYPE) { // top
@Override
protected Point getLocation(DecorationLayer layer, RadComponent component) {
Point location = super.getLocation(layer, component);
location.y -= ((RadViewComponent)component).getMargins().y;
return location;
}
});
pointBottom(decorator, Color.orange, 0.25, TYPE);
}
protected static void pointFeedback(ResizeSelectionDecorator decorator) {
decorator.addPoint(new ResizePoint() {
@Override
protected void paint(DecorationLayer layer, Graphics2D g, RadComponent component) {
Rectangle bounds = component.getBounds(layer);
@@ -216,44 +253,28 @@ public class LayoutMarginOperation implements EditOperation {
return null;
}
});
}
decorator.addPoint(new DirectionResizePoint(Color.orange, Color.black, Position.WEST, LayoutMarginOperation.TYPE) { // left
protected static void pointRight(ResizeSelectionDecorator decorator, Color color, double ySeparator, Object type) {
decorator.addPoint(new DirectionResizePoint(color, Color.black, Position.EAST, type) {
@Override
protected Point getLocation(DecorationLayer layer, RadComponent component) {
Point location = super.getLocation(layer, component);
location.x -= ((RadViewComponent)component).getMargins().x;
location.x += ((RadViewComponent)component).getMargins().width;
return location;
}
});
}.move(1, ySeparator));
}
decorator
.addPoint(new DirectionResizePoint(Color.orange, Color.black, Position.EAST, LayoutMarginOperation.TYPE) { // right
@Override
protected Point getLocation(DecorationLayer layer, RadComponent component) {
Point location = super.getLocation(layer, component);
location.x += ((RadViewComponent)component).getMargins().width;
return location;
}
}.move(1, 0.25));
decorator.addPoint(new DirectionResizePoint(Color.orange, Color.black, Position.NORTH, LayoutMarginOperation.TYPE) { // top
protected static void pointBottom(ResizeSelectionDecorator decorator, Color color, double xSeparator, Object type) {
decorator.addPoint(new DirectionResizePoint(color, Color.black, Position.SOUTH, type) {
@Override
protected Point getLocation(DecorationLayer layer, RadComponent component) {
Point location = super.getLocation(layer, component);
location.y -= ((RadViewComponent)component).getMargins().y;
location.y += ((RadViewComponent)component).getMargins().height;
return location;
}
});
decorator.addPoint(
new DirectionResizePoint(Color.orange, Color.black, Position.SOUTH, LayoutMarginOperation.TYPE) { // bottom
@Override
protected Point getLocation(DecorationLayer layer, RadComponent component) {
Point location = super.getLocation(layer, component);
location.y += ((RadViewComponent)component).getMargins().height;
return location;
}
}.move(0.25, 1));
}.move(xSeparator, 1));
}
private static void applyMargins(Rectangle bounds, Rectangle margins) {
@@ -0,0 +1,122 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.android.designer.designSurface.layout;
import com.intellij.designer.designSurface.OperationContext;
import com.intellij.designer.designSurface.selection.ResizeSelectionDecorator;
import com.intellij.designer.model.RadComponent;
import com.intellij.designer.utils.Position;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.psi.xml.XmlAttribute;
import java.awt.*;
import java.text.DecimalFormat;
/**
* @author Alexander Lobas
*/
public class LayoutWeightOperation extends LayoutMarginOperation {
public static final String TYPE = "layout_weight";
private float myWeight;
public LayoutWeightOperation(OperationContext context) {
super(context);
}
@Override
public void setComponent(RadComponent component) {
super.setComponent(component);
try {
myWeight = Float.parseFloat(myComponent.getTag().getAttributeValue("android:layout_weight"));
}
catch (Throwable e) {
myWeight = 0;
}
}
@Override
protected Color getFeedbackColor() {
return Color.cyan;
}
@Override
protected void fillTextFeedback() {
Dimension sizeDelta = myContext.getSizeDelta();
int direction = myContext.getResizeDirection();
if (direction == Position.EAST) { // right
myTextFeedback.append(getWeight(sizeDelta.width));
}
else if (direction == Position.SOUTH) { // bottom
myTextFeedback.append(getWeight(sizeDelta.height));
}
}
private static final DecimalFormat FORMAT = new DecimalFormat("#.##");
private String getWeight(int value) {
double weight = myWeight + value / 100.0;
if (weight <= 0) {
return "0";
}
return FORMAT.format(weight);
}
@Override
public void execute() throws Exception {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
Dimension sizeDelta = myContext.getSizeDelta();
int direction = myContext.getResizeDirection();
if (direction == Position.EAST) { // right
setWeight(sizeDelta.width);
}
else if (direction == Position.SOUTH) { // bottom
setWeight(sizeDelta.height);
}
}
});
}
private void setWeight(int value) {
float weight = myWeight + value / 100f;
if (weight <= 0) {
XmlAttribute attribute = myComponent.getTag().getAttribute("android:layout_weight");
if (attribute != null) {
attribute.delete();
}
}
else {
myComponent.getTag().setAttribute("android:layout_weight", FORMAT.format(weight).replace(',', '.'));
}
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// ResizePoint
//
//////////////////////////////////////////////////////////////////////////////////////////
public static void point(ResizeSelectionDecorator decorator) {
pointFeedback(decorator);
pointRight(decorator, Color.cyan, 0.75, TYPE);
pointBottom(decorator, Color.cyan, 0.75, TYPE);
}
}
@@ -209,6 +209,9 @@ public class ResizeOperation implements EditOperation {
createFeedback();
myBounds = myContext.getTransformedRectangle(myComponent.getBounds(myContext.getArea().getFeedbackLayer()));
myBounds.width = Math.max(myBounds.width, 0);
myBounds.height = Math.max(myBounds.height, 0);
int direction = myContext.getResizeDirection();
if ((direction & Position.EAST) != 0) {
Binary file not shown.

After

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 506 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 B

@@ -0,0 +1,69 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.android.designer.model.layout;
import com.intellij.android.designer.designSurface.TreeDropToOperation;
import com.intellij.android.designer.designSurface.layout.AbsoluteLayoutOperation;
import com.intellij.android.designer.designSurface.layout.ResizeOperation;
import com.intellij.android.designer.model.RadViewComponent;
import com.intellij.android.designer.model.RadViewLayoutWithData;
import com.intellij.designer.designSurface.ComponentDecorator;
import com.intellij.designer.designSurface.EditOperation;
import com.intellij.designer.designSurface.OperationContext;
import com.intellij.designer.designSurface.selection.ResizeSelectionDecorator;
import com.intellij.designer.model.RadComponent;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.util.List;
/**
* @author Alexander Lobas
*/
public class RadAbsoluteLayout extends RadViewLayoutWithData {
private static final String[] LAYOUT_PARAMS = {"AbsoluteLayout_Layout", "ViewGroup_Layout"};
private ResizeSelectionDecorator mySelectionDecorator;
@Override
@NotNull
public String[] getLayoutParams() {
return LAYOUT_PARAMS;
}
@Override
public EditOperation processChildOperation(OperationContext context) {
if (context.isCreate() || context.isPaste() || context.isAdd() || context.isMove()) {
if (context.isTree()) {
return new TreeDropToOperation(myContainer, context);
}
return new AbsoluteLayoutOperation((RadViewComponent)myContainer, context);
}
if (context.is(ResizeOperation.TYPE)) {
return new ResizeOperation(context);
}
return null;
}
@Override
public ComponentDecorator getChildSelectionDecorator(RadComponent component, List<RadComponent> selection) {
if (mySelectionDecorator == null) {
mySelectionDecorator = new ResizeSelectionDecorator(Color.red, 1);
ResizeOperation.points(mySelectionDecorator);
}
return mySelectionDecorator;
}
}
@@ -16,10 +16,7 @@
package com.intellij.android.designer.model.layout;
import com.intellij.android.designer.designSurface.TreeDropToOperation;
import com.intellij.android.designer.designSurface.layout.FlowStaticDecorator;
import com.intellij.android.designer.designSurface.layout.LayoutMarginOperation;
import com.intellij.android.designer.designSurface.layout.LinearLayoutOperation;
import com.intellij.android.designer.designSurface.layout.ResizeOperation;
import com.intellij.android.designer.designSurface.layout.*;
import com.intellij.android.designer.model.RadViewComponent;
import com.intellij.android.designer.model.RadViewLayoutWithData;
import com.intellij.designer.actions.AbstractComboBoxAction;
@@ -64,7 +61,7 @@ public class RadLinearLayout extends RadViewLayoutWithData implements ILayoutDec
return LAYOUT_PARAMS;
}
private boolean isHorizontal() {
protected boolean isHorizontal() {
return !"vertical".equals(((RadViewComponent)myContainer).getTag().getAttributeValue("android:orientation"));
}
@@ -82,6 +79,9 @@ public class RadLinearLayout extends RadViewLayoutWithData implements ILayoutDec
else if (context.is(LayoutMarginOperation.TYPE)) {
return new LayoutMarginOperation(context);
}
else if (context.is(LayoutWeightOperation.TYPE)) {
return new LayoutWeightOperation(context);
}
return null;
}
@@ -115,6 +115,8 @@ public class RadLinearLayout extends RadViewLayoutWithData implements ILayoutDec
}
}
private static final int POINTS_SIZE = 16;
@Override
public ComponentDecorator getChildSelectionDecorator(RadComponent component, List<RadComponent> selection) {
if (mySelectionDecorator == null) {
@@ -125,18 +127,31 @@ public class RadLinearLayout extends RadViewLayoutWithData implements ILayoutDec
boolean horizontal = isHorizontal();
Pair<Gravity, Gravity> gravity = Gravity.getSides(component);
int direction = ((DirectionResizePoint)point).getDirection();
Rectangle bounds = component.getBounds();
boolean goodWidth = bounds.width >= POINTS_SIZE;
boolean goodHeight = bounds.height >= POINTS_SIZE;
if (direction == Position.WEST) { // left
return horizontal || gravity.first != Gravity.right;
return (horizontal || gravity.first != Gravity.right) && goodHeight;
}
if (direction == Position.EAST) { // right
return horizontal || gravity.first != Gravity.left;
return (horizontal || gravity.first != Gravity.left) && goodHeight;
}
if (direction == Position.NORTH) { // top
return !horizontal || gravity.second != Gravity.bottom;
return (!horizontal || gravity.second != Gravity.bottom) && goodWidth;
}
if (direction == Position.SOUTH) { // bottom
return !horizontal || gravity.second != Gravity.top;
return (!horizontal || gravity.second != Gravity.top) && goodWidth;
}
}
if (point.getType() == LayoutWeightOperation.TYPE) {
int direction = ((DirectionResizePoint)point).getDirection();
if (direction == Position.EAST) { // right
return isHorizontal() && component.getBounds().height >= POINTS_SIZE;
}
if (direction == Position.SOUTH) { // bottom
return !isHorizontal() && component.getBounds().width >= POINTS_SIZE;
}
}
return true;
@@ -147,6 +162,7 @@ public class RadLinearLayout extends RadViewLayoutWithData implements ILayoutDec
mySelectionDecorator.clear();
if (selection.size() == 1) {
LayoutMarginOperation.points(mySelectionDecorator);
LayoutWeightOperation.point(mySelectionDecorator);
}
ResizeOperation.points(mySelectionDecorator);
@@ -0,0 +1,28 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.android.designer.model.layout;
import com.intellij.android.designer.model.RadViewComponent;
/**
* @author Alexander Lobas
*/
public class RadRadioGroupLayout extends RadLinearLayout {
@Override
protected boolean isHorizontal() {
return "horizontal".equals(((RadViewComponent)myContainer).getTag().getAttributeValue("android:orientation"));
}
}
@@ -545,6 +545,26 @@
</creation>
</meta>
<meta model="com.intellij.android.designer.model.RadViewComponent"
class="android.gesture.GestureOverlayView"
tag="GestureOverlayView">
<palette title="GestureOverlayView" icon="/com/intellij/android/designer/icons/GestureOverlayView.png"
tooltip="A transparent overlay for gesture input that can be placed on top of other widgets or contain other widgets."/>
<properties important="gestureColor orientation"/>
<creation>
<![CDATA[
<GestureOverlayView
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</GestureOverlayView>
]]>
</creation>
</meta>
<meta model="com.intellij.android.designer.model.RadViewComponent"
class="android.view.ViewStub"
tag="ViewStub">
@@ -983,6 +1003,28 @@
</creation>
</meta>
<meta model="com.intellij.android.designer.model.RadViewContainer"
layout="com.intellij.android.designer.model.layout.RadRadioGroupLayout"
class="android.widget.RadioGroup"
tag="RadioGroup">
<presentation title=" (%orientation%)"/>
<palette title="RadioGroup" icon="/com/intellij/android/designer/icons/RadioGroup.png"
tooltip="This class is used to create a multiple-exclusion scope for a set of radio buttons. Checking one radio button that belongs to a radio group unchecks any previously checked radio button within the same group."/>
<properties important="orientation checkedButton" top="gravity orientation"/>
<creation>
<![CDATA[
<RadioGroup
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</RadioGroup>
]]>
</creation>
</meta>
<!-- ================= Layouts ================= -->
<meta model="com.intellij.android.designer.model.RadViewContainer"
@@ -1032,6 +1074,24 @@
</creation>
</meta>
<meta model="com.intellij.android.designer.model.RadViewContainer"
layout="com.intellij.android.designer.model.layout.RadAbsoluteLayout"
class="android.widget.AbsoluteLayout"
tag="AbsoluteLayout">
<palette title="AbsoluteLayout" icon="/com/intellij/android/designer/icons/AbsoluteLayout.png"
tooltip="A layout that lets you specify exact locations (x/y coordinates) of its children. Absolute layouts are less flexible and harder to maintain than other types of layouts without absolute positioning."/>
<creation>
<![CDATA[
<AbsoluteLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</AbsoluteLayout>
]]>
</creation>
</meta>
<!-- ================= Palette ================= -->
<palette>
@@ -1063,6 +1123,7 @@
<item tag="MediaController"/>
<item tag="WebView"/>
<item tag="KeyboardView"/>
<item tag="GestureOverlayView"/>
<item tag="SurfaceView"/>
<item tag="TextureView"/>
</group>
@@ -1073,6 +1134,7 @@
<item tag="NumberPicker"/>
<item tag="ZoomControls"/>
<item tag="SearchView"/>
<item tag="RadioGroup"/>
<item tag="ListView"/>
<item tag="GridView"/>
<item tag="Gallery"/>
@@ -60,6 +60,7 @@ public class ResourceRenderer implements PropertyRenderer {
String value = (String)object;
if (myBooleanRenderer != null && (StringUtil.isEmpty(value) || "false".equals(value) || "true".equals(value))) {
myBooleanRenderer.setText(value);
return myBooleanRenderer.getComponent(component, "true".equals(value), selected, hasFocus);
}
@@ -52,7 +52,9 @@ public class AndroidCommonUtils {
private static final Pattern WARNING_PATTERN = Pattern.compile(".*warning.*");
private static final Pattern ERROR_PATTERN = Pattern.compile(".*error.*");
private static final Pattern EXCEPTION_PATTERN = Pattern.compile(".*exception.*");
private static Pattern R_PATTERN = Pattern.compile("R(\\$.*)?\\.class");
private static Pattern MANIFEST_PATTERN = Pattern.compile("Manifest(\\$.*)?\\.class");
public static final Pattern COMPILER_MESSAGE_PATTERN = Pattern.compile("(.+):(\\d+):.+");
@@ -204,7 +206,7 @@ public class AndroidCommonUtils {
private static void addFileToJar(@NotNull File file,
@NotNull File rootDirectory,
boolean packRClasses,
boolean packRAndManifestClasses,
@NotNull List<Pair<File, String>> files)
throws IOException {
@@ -213,7 +215,7 @@ public class AndroidCommonUtils {
if (children != null) {
for (File child : children) {
addFileToJar(child, rootDirectory, packRClasses, files);
addFileToJar(child, rootDirectory, packRAndManifestClasses, files);
}
}
}
@@ -222,7 +224,9 @@ public class AndroidCommonUtils {
return;
}
if (!packRClasses && R_PATTERN.matcher(file.getName()).matches()) {
if (!packRAndManifestClasses &&
(R_PATTERN.matcher(file.getName()).matches() ||
MANIFEST_PATTERN.matcher(file.getName()).matches())) {
return;
}
@@ -24,6 +24,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
@@ -174,8 +175,9 @@ public class AndroidResourcesLineMarkerProvider implements LineMarkerProvider {
private static Map<MyResourceEntry, List<PsiElement>> buildLocalResourceMap(@NotNull Project project,
@NotNull final LocalResourceManager resManager) {
final Map<MyResourceEntry, List<PsiElement>> result = new HashMap<MyResourceEntry, List<PsiElement>>();
Collection<Resources> resourceFiles = resManager.getResourceElements();
for (Resources res : resourceFiles) {
List<Pair<Resources,VirtualFile>> resourceFiles = resManager.getResourceElements();
for (Pair<Resources, VirtualFile> pair : resourceFiles) {
final Resources res = pair.getFirst();
for (ResourceType valueResourceType : AndroidResourceUtil.VALUE_RESOURCE_TYPES) {
for (ResourceElement valueResource : AndroidResourceUtil.getValueResourcesFromElement(valueResourceType.getName(), res)) {
addResource(valueResourceType.getName(), valueResource, result);
@@ -729,8 +729,9 @@ public class AndroidCompileUtil {
}
}
for (final Resources resources : manager.getResourceElements()) {
waitForSmartMode(project);
for (final Pair<Resources, VirtualFile> pair : manager.getResourceElements()) {
final Resources resources = pair.getFirst();
waitForSmartMode(project);
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
@@ -19,10 +19,7 @@ import com.intellij.compiler.CompilerConfiguration;
import com.intellij.compiler.CompilerConfigurationImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.compiler.CompilationStatusAdapter;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompileTask;
import com.intellij.openapi.compiler.CompilerManager;
import com.intellij.openapi.compiler.*;
import com.intellij.openapi.compiler.options.ExcludeEntryDescription;
import com.intellij.openapi.compiler.options.ExcludedEntriesConfiguration;
import com.intellij.openapi.diagnostic.Logger;
@@ -31,7 +28,10 @@ import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.DependencyScope;
import com.intellij.openapi.roots.ModuleOrderEntry;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
@@ -39,6 +39,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.hash.HashSet;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.facet.AndroidRootUtil;
import org.jetbrains.android.maven.AndroidMavenUtil;
import org.jetbrains.android.sdk.AndroidPlatform;
import org.jetbrains.android.util.AndroidCommonUtils;
import org.jetbrains.annotations.NotNull;
@@ -57,6 +58,8 @@ public class AndroidPrecompileTask implements CompileTask {
@Override
public boolean execute(CompileContext context) {
checkAndroidDependencies(context);
final Project project = context.getProject();
ExcludedEntriesConfiguration configuration =
@@ -109,6 +112,42 @@ public class AndroidPrecompileTask implements CompileTask {
}
return true;
}
private static void checkAndroidDependencies(@NotNull CompileContext context) {
for (Module module : context.getCompileScope().getAffectedModules()) {
final AndroidFacet facet = AndroidFacet.getInstance(module);
if (facet != null && !facet.getConfiguration().LIBRARY_PROJECT) {
for (OrderEntry entry : ModuleRootManager.getInstance(module).getOrderEntries()) {
if (entry instanceof ModuleOrderEntry) {
final ModuleOrderEntry moduleOrderEntry = (ModuleOrderEntry)entry;
if (moduleOrderEntry.getScope() == DependencyScope.COMPILE) {
final Module depModule = moduleOrderEntry.getModule();
if (depModule != null) {
final AndroidFacet depFacet = AndroidFacet.getInstance(depModule);
if (depFacet != null && !depFacet.getConfiguration().LIBRARY_PROJECT) {
String message = "Suspicious module dependency " +
module.getName() +
" -> " +
depModule.getName() +
": Android application module depends on other application module. Possibly, you should ";
if (AndroidMavenUtil.isMavenizedModule(depModule)) {
message += "change packaging type of module " + depModule.getName() + " to 'apklib' in pom.xml file or ";
}
message += "change dependency scope to 'Provided'.";
context.addMessage(CompilerMessageCategory.WARNING, message, null, -1, -1);
}
}
}
}
}
}
}
}
private static void clearResCache(@NotNull AndroidFacet facet, @NotNull CompileContext context) {
final Module module = facet.getModule();
@@ -1,29 +1,44 @@
package org.jetbrains.android.compiler;
import com.android.resources.ResourceType;
import com.android.sdklib.IAndroidTarget;
import com.intellij.openapi.compiler.ValidityState;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.ContentIterator;
import com.intellij.openapi.roots.impl.FileIndexImplUtil;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.HashSet;
import com.intellij.openapi.vfs.VirtualFileFilter;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.HashMap;
import org.jetbrains.android.dom.resources.ResourceElement;
import org.jetbrains.android.dom.resources.Resources;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.facet.AndroidRootUtil;
import org.jetbrains.android.resourceManagers.LocalResourceManager;
import org.jetbrains.android.resourceManagers.ResourceManager;
import org.jetbrains.android.sdk.AndroidPlatform;
import org.jetbrains.android.util.AndroidResourceUtil;
import org.jetbrains.android.util.ResourceEntry;
import org.jetbrains.annotations.NotNull;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Set;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* @author Eugene.Kudelevsky
*/
public class ResourceNamesValidityState implements ValidityState {
private final Set<ResourceEntry> myResourcesSet = new HashSet<ResourceEntry>();
private final Map<String, MyResourceFileData> myResources = new HashMap<String, MyResourceFileData>();
private final String myAndroidTargetHashString;
private final long myManifestTimestamp;
public ResourceNamesValidityState(@NotNull Module module) {
final AndroidFacet facet = AndroidFacet.getInstance(module);
assert facet != null;
@@ -35,19 +50,83 @@ public class ResourceNamesValidityState implements ValidityState {
final VirtualFile manifestFile = AndroidRootUtil.getManifestFile(facet);
myManifestTimestamp = manifestFile != null ? manifestFile.getModificationStamp() : -1;
AndroidCompileUtil.collectAllResources(facet, myResourcesSet);
final LocalResourceManager manager = facet.getLocalResourceManager();
for (final Pair<Resources, VirtualFile> pair : manager.getResourceElements()) {
final Resources resources = pair.getFirst();
final VirtualFile file = pair.getSecond();
for (final ResourceType resType : AndroidResourceUtil.VALUE_RESOURCE_TYPES) {
addValueResources(file, resType, AndroidResourceUtil.getValueResourcesFromElement(resType.getName(), resources), myResources);
}
addValueResources(file, ResourceType.ATTR, resources.getAttrs(), myResources);
addValueResources(file, ResourceType.DECLARE_STYLEABLE, resources.getDeclareStyleables(), myResources);
}
for (final VirtualFile subdir : manager.getResourceSubdirs(null)) {
final String subdirName = subdir.getName();
final int index = subdirName.indexOf('-');
final String typeName = index >= 0 ? subdirName.substring(0, index) : subdirName;
final ResourceType type = ResourceType.getEnum(typeName);
final boolean idProvidingResource = type != null && ArrayUtil.find(ResourceManager.ID_PROVIDING_RESOURCE_TYPES, type) >= 0;
FileIndexImplUtil.iterateRecursively(subdir, VirtualFileFilter.ALL, new ContentIterator() {
@Override
public boolean processFile(VirtualFile fileOrDir) {
if (!fileOrDir.isDirectory()) {
MyResourceFileData data = myResources.get(fileOrDir.getPath());
if (data == null) {
data = new MyResourceFileData();
myResources.put(fileOrDir.getPath(), data);
}
if (idProvidingResource) {
data.setTimestamp(fileOrDir.getTimeStamp());
}
}
return true;
}
});
}
}
private static void addValueResources(VirtualFile file,
ResourceType resType,
Collection<? extends ResourceElement> resourceElements,
Map<String, MyResourceFileData> result) {
for (ResourceElement element : resourceElements) {
final String name = element.getName().getValue();
if (name != null) {
MyResourceFileData data = result.get(file.getPath());
if (data == null) {
data = new MyResourceFileData();
result.put(file.getPath(), data);
}
data.addValueResource(new ResourceEntry(resType.getName(), name));
}
}
}
public ResourceNamesValidityState(@NotNull DataInput in) throws IOException {
myAndroidTargetHashString = in.readUTF();
myManifestTimestamp = in.readLong();
final int resourcesCount = in.readInt();
for (int i = 0; i < resourcesCount; i++) {
final String type = in.readUTF();
final String name = in.readUTF();
myResourcesSet.add(new ResourceEntry(type, name));
final String filePath = in.readUTF();
final int valueResourcesCount = in.readInt();
final List<ResourceEntry> valueResources = new ArrayList<ResourceEntry>(valueResourcesCount);
for (int j = 0; j < valueResourcesCount; j++) {
final String resType = in.readUTF();
final String resName = in.readUTF();
valueResources.add(new ResourceEntry(resType, resName));
}
final long fileTimestamp = in.readLong();
myResources.put(filePath, new MyResourceFileData(valueResources, fileTimestamp));
}
}
@@ -56,24 +135,86 @@ public class ResourceNamesValidityState implements ValidityState {
if (!(otherState instanceof ResourceNamesValidityState)) {
return false;
}
final ResourceNamesValidityState other = (ResourceNamesValidityState)otherState;
return other.myAndroidTargetHashString.equals(myAndroidTargetHashString) &&
other.myManifestTimestamp == myManifestTimestamp &&
other.myResourcesSet.equals(myResourcesSet);
other.myResources.equals(myResources);
}
@Override
public void save(DataOutput out) throws IOException {
out.writeUTF(myAndroidTargetHashString);
out.writeLong(myManifestTimestamp);
out.writeInt(myResourcesSet.size());
for (ResourceEntry resourceEntry : myResourcesSet) {
out.writeUTF(resourceEntry.getType());
out.writeUTF(resourceEntry.getName());
out.writeInt(myResources.size());
for (Map.Entry<String, MyResourceFileData> entry : myResources.entrySet()) {
out.writeUTF(entry.getKey());
final MyResourceFileData data = entry.getValue();
final List<ResourceEntry> valueResources = data.getValueResources();
out.writeInt(valueResources.size());
for (ResourceEntry resource : valueResources) {
out.writeUTF(resource.getType());
out.writeUTF(resource.getName());
}
out.writeLong(data.getTimestamp());
}
}
private static class MyResourceFileData {
// order matters because of id assigning in R.java
private final List<ResourceEntry> myValueResources;
private long myTimestamp;
MyResourceFileData() {
this(new ArrayList<ResourceEntry>(), 0);
}
private MyResourceFileData(@NotNull List<ResourceEntry> valueResources, long timestamp) {
myValueResources = valueResources;
myTimestamp = timestamp;
}
@NotNull
List<ResourceEntry> getValueResources() {
return myValueResources;
}
long getTimestamp() {
return myTimestamp;
}
public void setTimestamp(long timestamp) {
myTimestamp = timestamp;
}
public void addValueResource(@NotNull ResourceEntry entry) {
myValueResources.add(entry);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MyResourceFileData data = (MyResourceFileData)o;
if (myTimestamp != data.myTimestamp) return false;
if (!myValueResources.equals(data.myValueResources)) return false;
return true;
}
@Override
public int hashCode() {
int result = myValueResources.hashCode();
result = 31 * result + (int)(myTimestamp ^ (myTimestamp >>> 32));
return result;
}
}
}
@@ -24,6 +24,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.ReadonlyStatusHandler;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
@@ -96,7 +97,7 @@ public class LocalResourceManager extends ResourceManager {
return AndroidRootUtil.getResourceDir(getFacet());
}
public List<Resources> getResourceElements() {
public List<Pair<Resources, VirtualFile>> getResourceElements() {
return getResourceElements(null);
}
@@ -200,7 +201,8 @@ public class LocalResourceManager extends ResourceManager {
@NotNull
public List<Attr> findAttrs(@NotNull String name) {
List<Attr> list = new ArrayList<Attr>();
for (Resources res : getResourceElements()) {
for (Pair<Resources, VirtualFile> pair : getResourceElements()) {
final Resources res = pair.getFirst();
for (Attr attr : res.getAttrs()) {
if (name.equals(attr.getName().getValue())) {
list.add(attr);
@@ -219,7 +221,8 @@ public class LocalResourceManager extends ResourceManager {
public List<DeclareStyleable> findStyleables(@NotNull String name) {
List<DeclareStyleable> list = new ArrayList<DeclareStyleable>();
for (Resources res : getResourceElements()) {
for (Pair<Resources, VirtualFile> pair : getResourceElements()) {
final Resources res = pair.getFirst();
for (DeclareStyleable styleable : res.getDeclareStyleables()) {
if (name.equals(styleable.getName().getValue())) {
list.add(styleable);
@@ -17,11 +17,11 @@ package org.jetbrains.android.resourceManagers;
import com.android.resources.ResourceType;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
@@ -53,7 +53,9 @@ import static java.util.Collections.addAll;
* @author coyote
*/
public abstract class ResourceManager {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.resourceManagers.LocalResourceManager");
public static final ResourceType[] ID_PROVIDING_RESOURCE_TYPES = new ResourceType[] {
ResourceType.LAYOUT, ResourceType.MENU
};
protected final Module myModule;
protected final AndroidFacet myFacet;
@@ -130,17 +132,19 @@ public abstract class ResourceManager {
return findResourceFiles(resType, null, true);
}
protected List<Resources> getResourceElements(@Nullable Set<VirtualFile> files) {
protected List<Pair<Resources, VirtualFile>> getResourceElements(@Nullable Set<VirtualFile> files) {
return getRootDomElements(Resources.class, files);
}
private <T extends DomElement> List<T> getRootDomElements(@NotNull Class<T> elementType,
@Nullable Set<VirtualFile> files) {
final List<T> result = new ArrayList<T>();
private <T extends DomElement> List<Pair<T, VirtualFile>> getRootDomElements(@NotNull Class<T> elementType,
@Nullable Set<VirtualFile> files) {
final List<Pair<T, VirtualFile>> result = new ArrayList<Pair<T, VirtualFile>>();
for (VirtualFile file : getAllValueResourceFiles()) {
if ((files == null || files.contains(file)) && file.isValid()) {
T element = AndroidUtils.loadDomElement(myModule, file, elementType);
if (element != null) result.add(element);
final T element = AndroidUtils.loadDomElement(myModule, file, elementType);
if (element != null) {
result.add(new Pair<T, VirtualFile>(element, file));
}
}
}
return result;
@@ -162,8 +166,9 @@ public abstract class ResourceManager {
protected List<ResourceElement> getValueResources(@NotNull final String resourceType, @Nullable Set<VirtualFile> files) {
final List<ResourceElement> result = new ArrayList<ResourceElement>();
Collection<Resources> resourceFiles = getResourceElements(files);
for (final Resources resources : resourceFiles) {
List<Pair<Resources, VirtualFile>> resourceFiles = getResourceElements(files);
for (final Pair<Resources, VirtualFile> pair : resourceFiles) {
final Resources resources = pair.getFirst();
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
@@ -337,10 +342,11 @@ public abstract class ResourceManager {
}
@NotNull
private List<VirtualFile> getResourceSubdirsToSearchIds() {
public List<VirtualFile> getResourceSubdirsToSearchIds() {
final List<VirtualFile> resSubdirs = new ArrayList<VirtualFile>();
resSubdirs.addAll(getResourceSubdirs(ResourceType.LAYOUT.getName()));
resSubdirs.addAll(getResourceSubdirs(ResourceType.MENU.getName()));
for (ResourceType type : ID_PROVIDING_RESOURCE_TYPES) {
resSubdirs.addAll(getResourceSubdirs(type.getName()));
}
return resSubdirs;
}
@@ -77,7 +77,7 @@ public class GitBranchUiUtil {
*/
@Nullable
public static String getNewBranchNameFromUser(@NotNull Project project, @NotNull Collection<GitRepository> repositories, @NotNull String dialogTitle) {
return Messages.showInputDialog(project, "Enter the name of new branch", dialogTitle, Messages.getQuestionIcon(), "",
return Messages.showInputDialog(project, "Enter the name of new branch:", dialogTitle, Messages.getQuestionIcon(), "",
GitNewBranchNameValidator.newInstance(repositories));
}
@@ -17,6 +17,7 @@
package org.jetbrains.plugins.groovy.codeInsight;
import com.intellij.codeInsight.TargetElementEvaluator;
import com.intellij.openapi.util.Key;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiReference;
@@ -34,6 +35,9 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrRenameableLightEle
* @author Maxim.Medvedev
*/
public class GroovyTargetElementEvaluator implements TargetElementEvaluator {
public static final Key<Object> NAVIGATION_ELEMENT_IS_NOT_TARGET = Key.create("GroovyTargetElementEvaluator.DONT_FOLLOW_NAVIGATION_ELEMENT");
public boolean includeSelfInGotoImplementation(@NotNull PsiElement element) {
return false;
}
@@ -79,7 +83,8 @@ public class GroovyTargetElementEvaluator implements TargetElementEvaluator {
@Nullable
public static PsiElement correctSearchTargets(@Nullable PsiElement target) {
if (target != null && !(target instanceof GrAccessorMethod) && !target.isPhysical()) {
if (target != null && !(target instanceof GrAccessorMethod) && !target.isPhysical()
&& target.getUserData(NAVIGATION_ELEMENT_IS_NOT_TARGET) == null) {
return target.getNavigationElement();
}
return target;
@@ -95,8 +95,10 @@ public class MavenRepositoriesConfigurable extends BaseConfigurable implements S
final String value = (String)myServiceList.getSelectedValue();
final String text = Messages.showInputDialog("Artifactory or Nexus Service URL", "Add Service URL", Messages.getQuestionIcon(),
value == null ? "http://" : value, new URLInputVaslidator());
myModel.add(text);
myServiceList.setSelectedValue(text, true);
if (StringUtil.isNotEmpty(text)) {
myModel.add(text);
myServiceList.setSelectedValue(text, true);
}
}
});
myEditButton.addActionListener(new ActionListener() {
@@ -105,7 +107,7 @@ public class MavenRepositoriesConfigurable extends BaseConfigurable implements S
final int index = myServiceList.getSelectedIndex();
final String text = Messages.showInputDialog("Artifactory or Nexus Service URL", "Edit Service URL", Messages.getQuestionIcon(),
myModel.getElementAt(index), new URLInputVaslidator());
if (text != null) {
if (StringUtil.isNotEmpty(text)) {
myModel.setElementAt(text, index);
}
}
@@ -125,20 +125,24 @@ public class MavenArtifactUtil {
if (!file.exists()) return null;
ZipFile jar = new ZipFile(file);
ZipEntry entry = jar.getEntry(MAVEN_PLUGIN_DESCRIPTOR);
if (entry == null) {
MavenLog.LOG.info(IndicesBundle.message("repository.plugin.corrupt", file));
return null;
}
InputStream is = jar.getInputStream(entry);
try {
byte[] bytes = FileUtil.loadBytes(is);
return new MavenPluginInfo(bytes);
ZipEntry entry = jar.getEntry(MAVEN_PLUGIN_DESCRIPTOR);
if (entry == null) {
MavenLog.LOG.info(IndicesBundle.message("repository.plugin.corrupt", file));
return null;
}
InputStream is = jar.getInputStream(entry);
try {
byte[] bytes = FileUtil.loadBytes(is);
return new MavenPluginInfo(bytes);
}
finally {
is.close();
}
}
finally {
is.close();
jar.close();
}
}
@@ -145,7 +145,7 @@ public class DuplicatePropertyInspection extends GlobalSimpleInspectionTool {
private void checkFile(final PsiFile file, final InspectionManager manager, GlobalInspectionContextImpl context, final RefManager refManager, final ProblemDescriptionsProcessor processor) {
if (!(file instanceof PropertiesFile)) return;
if (!context.isToCheckMember(file, this)) return;
if (!context.isToCheckFile(file, this)) return;
final PsiSearchHelper searchHelper = PsiSearchHelper.SERVICE.getInstance(file.getProject());
final PropertiesFile propertiesFile = (PropertiesFile)file;
final List<IProperty> properties = propertiesFile.getProperties();
@@ -133140,6 +133140,7 @@ unwarrantably
unwarranted
unwary
unwashed
unwatch
unwatchable
unwatched
unwavering
@@ -31,6 +31,7 @@ import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
import com.intellij.codeInspection.htmlInspections.RequiredAttributesInspection;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.command.undo.UndoManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
@@ -170,6 +171,12 @@ public class XmlTagInsertHandler implements InsertHandler<LookupElement> {
if (myAttrValueMarker == null) {
return;
}
final UndoManager manager = UndoManager.getInstance(project);
if (manager.isUndoInProgress() || manager.isRedoInProgress()) {
return;
}
if (chooseAttributeName) {
final int startOffset = myAttrValueMarker.getStartOffset();
final int endOffset = myAttrValueMarker.getEndOffset();