/*
* Copyright 2003-2016 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 jetbrains.mps.nodeEditor;
import com.intellij.util.xmlb.annotations.AbstractCollection;
import com.intellij.util.xmlb.annotations.Attribute;
import com.intellij.util.xmlb.annotations.CollectionBean;
import com.intellij.util.xmlb.annotations.MapAnnotation;
import com.intellij.util.xmlb.annotations.OptionTag;
import com.intellij.util.xmlb.annotations.Property;
import com.intellij.util.xmlb.annotations.Tag;
import com.intellij.util.xmlb.annotations.Text;
import com.intellij.util.xmlb.annotations.Transient;
import org.jetbrains.annotations.Nullable;
import org.junit.Test;
import java.beans.FeatureDescriptor;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
public class EditorSettingsTest {
@Test
public void noMissingProperties() throws IntrospectionException {
Class<EditorSettings.MyState> clazz = EditorSettings.MyState.class;
PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(clazz).getPropertyDescriptors();
Set<String> fields = Stream.of(clazz.getDeclaredFields()).filter(this::notApplicable2FieldAccessor).map(EditorSettingsTest::getPropertyName).collect(
Collectors.toSet());
Set<String> writableProperties =
Stream.of(propertyDescriptors).filter(p -> p.getWriteMethod() != null).map(FeatureDescriptor::getName).collect(Collectors.toSet());
Set<String> missingProperties = new HashSet<>(fields);
missingProperties.removeAll(writableProperties);
assertThat("missing properties in " + EditorSettings.MyState.class, missingProperties, is(empty()));
}
@Nullable
private static String getPropertyName(Field field) {
return Introspector.decapitalize(field.getName().replaceFirst("^my", ""));
}
/**
* copied from {@link com.intellij.util.xmlb.BeanBinding#collectFieldAccessors(Class, List)}
*/
private boolean notApplicable2FieldAccessor(Field field) {
int modifiers = field.getModifiers();
boolean applicableToFieldAccessor = !Modifier.isStatic(modifiers) &&
(field.getAnnotation(OptionTag.class) != null ||
field.getAnnotation(Tag.class) != null ||
field.getAnnotation(Attribute.class) != null ||
field.getAnnotation(Property.class) != null ||
field.getAnnotation(Text.class) != null ||
field.getAnnotation(CollectionBean.class) != null ||
field.getAnnotation(MapAnnotation.class) != null ||
field.getAnnotation(AbstractCollection.class) != null ||
(Modifier.isPublic(modifiers) &&
// we don't want to allow final fields of all types, but only supported
(!Modifier.isFinal(modifiers) || Collection.class.isAssignableFrom(field.getType())) &&
!Modifier.isTransient(modifiers) &&
field.getAnnotation(Transient.class) == null));
return !applicableToFieldAccessor;
}
}