IDEA-76782 Generate runtime assertions for all configured not-null annotations

This commit is contained in:
peter
2016-09-19 12:04:52 +02:00
parent 35e27f05e9
commit 490d4e67bd
12 changed files with 143 additions and 68 deletions
@@ -21,14 +21,15 @@ import org.jetbrains.org.objectweb.asm.*;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
/**
* @author ven
*/
public class NotNullVerifyingInstrumenter extends ClassVisitor implements Opcodes {
private static final String NOT_NULL_CLASS_NAME = "org/jetbrains/annotations/NotNull";
private static final String SYNTHETIC_CLASS_NAME = "java/lang/Synthetic";
private static final String SYNTHETIC_TYPE = "L" + SYNTHETIC_CLASS_NAME + ";";
private static final String IAE_CLASS_NAME = "java/lang/IllegalArgumentException";
@@ -36,9 +37,6 @@ public class NotNullVerifyingInstrumenter extends ClassVisitor implements Opcode
private static final String ANNOTATION_DEFAULT_METHOD = "value";
private final String myNullArgMessageIndexed;
private final String myNullArgMessageNamed;
private final String myNullResultMessage;
@SuppressWarnings("SSBasedInspection") private static final String[] EMPTY_STRING_ARRAY = new String[0];
private final Map<String, Map<Integer, String>> myMethodParamNames;
@@ -46,22 +44,19 @@ public class NotNullVerifyingInstrumenter extends ClassVisitor implements Opcode
private boolean myIsModification = false;
private RuntimeException myPostponedError;
private final AuxiliaryMethodGenerator myAuxGenerator;
private final String myNotNullAnno;
private final Set<String> myNotNullAnnos = new HashSet<String>();
private NotNullVerifyingInstrumenter(final ClassVisitor classVisitor, ClassReader reader, String notNullAnnotation) {
private NotNullVerifyingInstrumenter(final ClassVisitor classVisitor, ClassReader reader, String[] notNullAnnotations) {
super(Opcodes.API_VERSION, classVisitor);
final String fullName = notNullAnnotation != null ? notNullAnnotation.replace('.', '/') : NOT_NULL_CLASS_NAME;
final String shortName = fullName.substring(fullName.lastIndexOf('/') + 1);
myNotNullAnno = "L" + fullName + ";";
myNullArgMessageIndexed = "Argument %s for @" + shortName + " parameter of %s.%s must not be null";
myNullArgMessageNamed = "Argument for @" + shortName + " parameter '%s' of %s.%s must not be null";
myNullResultMessage = "@" + shortName + " method %s.%s must not return null";
for (String annotation : notNullAnnotations) {
myNotNullAnnos.add("L" + annotation.replace('.', '/') + ";");
}
myMethodParamNames = getAllParameterNames(reader);
myAuxGenerator = new AuxiliaryMethodGenerator(reader);
}
public static boolean processClassFile(final FailSafeClassReader reader, final ClassVisitor writer, String notNullAnnotation) {
NotNullVerifyingInstrumenter instrumenter = new NotNullVerifyingInstrumenter(writer, reader, notNullAnnotation);
public static boolean processClassFile(final FailSafeClassReader reader, final ClassVisitor writer, String[] notNullAnnotations) {
NotNullVerifyingInstrumenter instrumenter = new NotNullVerifyingInstrumenter(writer, reader, notNullAnnotations);
reader.accept(instrumenter, 0);
instrumenter.myAuxGenerator.generateReportingMethod(writer);
return instrumenter.isModification();
@@ -121,10 +116,32 @@ public class NotNullVerifyingInstrumenter extends ClassVisitor implements Opcode
private static class NotNullState {
String message;
String exceptionType;
final String notNullAnno;
NotNullState(String exceptionType) {
NotNullState(String notNullAnno, String exceptionType) {
this.notNullAnno = notNullAnno;
this.exceptionType = exceptionType;
}
String getNullParamMessage(String paramName) {
if (message != null) return message;
final String shortName = getAnnoShortName();
if (paramName != null) return "Argument for @" + shortName + " parameter '%s' of %s.%s must not be null";
return "Argument %s for @" + shortName + " parameter of %s.%s must not be null";
}
String getNullResultMessage() {
if (message != null) return message;
final String shortName = getAnnoShortName();
return "@" + shortName + " method %s.%s must not return null";
}
private String getAnnoShortName() {
String fullName = notNullAnno.substring(1, notNullAnno.length() - 1); // "Lpk/name;" -> "pk/name"
return fullName.substring(fullName.lastIndexOf('/') + 1);
}
}
@Override
@@ -160,8 +177,8 @@ public class NotNullVerifyingInstrumenter extends ClassVisitor implements Opcode
public AnnotationVisitor visitParameterAnnotation(final int parameter, final String anno, final boolean visible) {
AnnotationVisitor av = mv.visitParameterAnnotation(parameter, anno, visible);
if (isReferenceType(args[parameter]) && anno.equals(myNotNullAnno)) {
NotNullState state = new NotNullState(IAE_CLASS_NAME);
if (isReferenceType(args[parameter]) && myNotNullAnnos.contains(anno)) {
NotNullState state = new NotNullState(anno, IAE_CLASS_NAME);
myNotNullParams.put(new Integer(parameter), state);
av = collectNotNullArgs(av, state);
}
@@ -176,8 +193,8 @@ public class NotNullVerifyingInstrumenter extends ClassVisitor implements Opcode
@Override
public AnnotationVisitor visitAnnotation(String anno, boolean isRuntime) {
AnnotationVisitor av = mv.visitAnnotation(anno, isRuntime);
if (isReferenceType(returnType) && anno.equals(myNotNullAnno)) {
myMethodNotNull = new NotNullState(ISE_CLASS_NAME);
if (isReferenceType(returnType) && myNotNullAnnos.contains(anno)) {
myMethodNotNull = new NotNullState(anno, ISE_CLASS_NAME);
av = collectNotNullArgs(av, myMethodNotNull);
}
@@ -203,9 +220,7 @@ public class NotNullVerifyingInstrumenter extends ClassVisitor implements Opcode
NotNullState state = entry.getValue();
String paramName = paramNames == null ? null : paramNames.get(param);
String descrPattern = state.message != null
? state.message
: paramName != null ? myNullArgMessageNamed : myNullArgMessageIndexed;
String descrPattern = state.getNullParamMessage(paramName);
String[] args = state.message != null
? EMPTY_STRING_ARRAY
: new String[]{paramName != null ? paramName : String.valueOf(param - mySyntheticCount), myClassName, name};
@@ -228,7 +243,7 @@ public class NotNullVerifyingInstrumenter extends ClassVisitor implements Opcode
mv.visitInsn(DUP);
final Label skipLabel = new Label();
mv.visitJumpInsn(IFNONNULL, skipLabel);
String descrPattern = myMethodNotNull.message != null ? myMethodNotNull.message : myNullResultMessage;
String descrPattern = myMethodNotNull.getNullResultMessage();
String[] args = myMethodNotNull.message != null ? EMPTY_STRING_ARRAY : new String[]{myClassName, name};
reportError(myMethodNotNull.exceptionType, skipLabel, descrPattern, args);
}
@@ -39,7 +39,7 @@ public class Javac2 extends Javac {
private ArrayList myFormFiles;
private List myNestedFormPathList;
private boolean instrumentNotNull = true;
private String myNotNull;
private String myNotNullAnnotations;
private List<Regexp> myClassFilterAnnotationRegexpList = new ArrayList<Regexp>(0);
public Javac2() {
@@ -76,12 +76,18 @@ public class Javac2 extends Javac {
this.instrumentNotNull = instrumentNotNull;
}
public String getNotNull() {
return myNotNull;
/**
* @return semicolon-separated names of not-null annotations to be instrumented. Example: <code>"org.jetbrains.annotations.NotNull;javax.annotation.Nonnull"</code>
*/
public String getNotNullAnnotations() {
return myNotNullAnnotations;
}
public void setNotNull(String notNull) {
myNotNull = notNull;
/**
* @param notNullAnnotations semicolon-separated names of not-null annotations to be instrumented. Example: <code>"org.jetbrains.annotations.NotNull;javax.annotation.Nonnull"</code>
*/
public void setNotNullAnnotations(String notNullAnnotations) {
myNotNullAnnotations = notNullAnnotations;
}
/**
@@ -447,7 +453,7 @@ public class Javac2 extends Javac {
if (version >= Opcodes.V1_5 && !shouldBeSkippedByAnnotationPattern(reader)) {
ClassWriter writer = new InstrumenterClassWriter(reader, getAsmClassWriterFlags(version), finder);
if (NotNullVerifyingInstrumenter.processClassFile(reader, writer, myNotNull)) {
if (NotNullVerifyingInstrumenter.processClassFile(reader, writer, myNotNullAnnotations.split(";"))) {
final FileOutputStream fileOutputStream = new FileOutputStream(path);
try {
fileOutputStream.write(writer.toByteArray());
@@ -18,9 +18,22 @@ package com.intellij.codeInsight;
import com.intellij.codeInspection.dataFlow.HardcodedContracts;
import com.intellij.openapi.components.State;
import com.intellij.psi.PsiElement;
import org.jetbrains.jps.model.serialization.java.compiler.JpsJavaCompilerNotNullableSerializer;
import java.util.List;
@State(name = "NullableNotNullManager")
public class NullableNotNullManagerImpl extends NullableNotNullManager {
public NullableNotNullManagerImpl() {
myNotNulls.addAll(getPredefinedNotNulls());
}
@Override
public List<String> getPredefinedNotNulls() {
return JpsJavaCompilerNotNullableSerializer.DEFAULT_NOT_NULLS;
}
protected boolean hasHardcodedContracts(PsiElement element) {
return HardcodedContracts.hasHardcodedContracts(element);
}
@@ -47,12 +47,8 @@ public abstract class NullableNotNullManager implements PersistentStateComponent
public static final String[] DEFAULT_NULLABLES = {AnnotationUtil.NULLABLE, JAVAX_ANNOTATION_NULLABLE,
"edu.umd.cs.findbugs.annotations.Nullable", "android.support.annotation.Nullable"
};
public static final String[] DEFAULT_NOT_NULLS = {AnnotationUtil.NOT_NULL, JAVAX_ANNOTATION_NONNULL,
"edu.umd.cs.findbugs.annotations.NonNull", "android.support.annotation.NonNull"
};
public NullableNotNullManager() {
Collections.addAll(myNotNulls, DEFAULT_NOT_NULLS);
Collections.addAll(myNullables, DEFAULT_NULLABLES);
}
@@ -78,7 +74,12 @@ public abstract class NullableNotNullManager implements PersistentStateComponent
public void setNotNulls(@NotNull String... annotations) {
myNotNulls.clear();
addAllIfNotPresent(myNotNulls, DEFAULT_NOT_NULLS);
for (String annotation : getPredefinedNotNulls()) {
LOG.assertTrue(annotation != null);
if (!myNotNulls.contains(annotation)) {
myNotNulls.add(annotation);
}
}
addAllIfNotPresent(myNotNulls, annotations);
}
@@ -210,7 +211,7 @@ public abstract class NullableNotNullManager implements PersistentStateComponent
if (type == null || TypeConversionUtil.isPrimitiveAndNotNull(type)) return null;
// even if javax.annotation.Nullable is not configured, it should still take precedence over ByDefault annotations
if (AnnotationUtil.isAnnotated(owner, Arrays.asList(nullable ? DEFAULT_NOT_NULLS : DEFAULT_NULLABLES), checkBases, false)) {
if (AnnotationUtil.isAnnotated(owner, nullable ? getPredefinedNotNulls() : Arrays.asList(DEFAULT_NULLABLES), checkBases, false)) {
return null;
}
@@ -329,7 +330,8 @@ public abstract class NullableNotNullManager implements PersistentStateComponent
}
public boolean hasDefaultValues() {
if (DEFAULT_NULLABLES.length != getNullables().size() || DEFAULT_NOT_NULLS.length != getNotNulls().size()) {
List<String> predefinedNotNulls = getPredefinedNotNulls();
if (DEFAULT_NULLABLES.length != getNullables().size() || predefinedNotNulls.size() != getNotNulls().size()) {
return false;
}
if (!myDefaultNotNull.equals(AnnotationUtil.NOT_NULL) || !myDefaultNullable.equals(AnnotationUtil.NULLABLE)) {
@@ -340,8 +342,8 @@ public abstract class NullableNotNullManager implements PersistentStateComponent
return false;
}
}
for (int i = 0; i < DEFAULT_NOT_NULLS.length; i++) {
if (!getNotNulls().get(i).equals(DEFAULT_NOT_NULLS[i])) {
for (int i = 0; i < predefinedNotNulls.size(); i++) {
if (!getNotNulls().get(i).equals(predefinedNotNulls.get(i))) {
return false;
}
}
@@ -376,7 +378,7 @@ public abstract class NullableNotNullManager implements PersistentStateComponent
Collections.addAll(myNullables, DEFAULT_NULLABLES);
}
if (myNotNulls.isEmpty()) {
Collections.addAll(myNotNulls, DEFAULT_NOT_NULLS);
myNotNulls.addAll(getPredefinedNotNulls());
}
}
catch (InvalidDataException e) {
@@ -391,4 +393,6 @@ public abstract class NullableNotNullManager implements PersistentStateComponent
public static boolean isNotNull(@NotNull PsiModifierListOwner owner) {
return getInstance(owner.getProject()).isNotNull(owner, true);
}
public abstract List<String> getPredefinedNotNulls();
}
@@ -0,0 +1,14 @@
@interface FooAnno {}
@interface BarAnno {}
public class MultipleAnnotations {
@FooAnno
public Object foo1() {
return null;
}
@BarAnno
public Object foo2() {
return null;
}
}
@@ -73,7 +73,7 @@ class Foo {
@Override
protected void tearDown() throws Exception {
NullableNotNullManager.getInstance(project).notNulls = NullableNotNullManager.DEFAULT_NOT_NULLS
NullableNotNullManager.getInstance(project).notNulls = NullableNotNullManager.getInstance(project).predefinedNotNulls as String[]
NullableNotNullManager.getInstance(project).defaultNotNull = AnnotationUtil.NOT_NULL
super.tearDown()
@@ -16,6 +16,7 @@
package com.intellij.compiler.notNullVerification;
import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.compiler.instrumentation.FailSafeClassReader;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
@@ -88,7 +89,7 @@ public class NotNullVerifyingInstrumenterTest extends UsefulTestCase {
}
public void testUseParameterNames() throws Exception {
Class<?> testClass = prepareTest(true);
Class<?> testClass = prepareTest(true, AnnotationUtil.NOT_NULL);
Constructor constructor = testClass.getConstructor(Object.class, Object.class);
verifyCallThrowsException("Argument for @NotNull parameter 'obj2' of UseParameterNames.<init> must not be null", null, constructor, null, null);
@@ -101,13 +102,13 @@ public class NotNullVerifyingInstrumenterTest extends UsefulTestCase {
}
public void testLongParameter() throws Exception {
Class<?> testClass = prepareTest(true);
Class<?> testClass = prepareTest(true, AnnotationUtil.NOT_NULL);
Method staticMethod = testClass.getMethod("foo", long.class, String.class, String.class);
verifyCallThrowsException("Argument for @NotNull parameter 'c' of LongParameter.foo must not be null", null, staticMethod, new Long(2), "z", null);
}
public void testDoubleParameter() throws Exception {
Class<?> testClass = prepareTest(true);
Class<?> testClass = prepareTest(true, AnnotationUtil.NOT_NULL);
Method staticMethod = testClass.getMethod("foo", double.class, String.class, String.class);
verifyCallThrowsException("Argument for @NotNull parameter 'c' of DoubleParameter.foo must not be null", null, staticMethod, new Long(2), "z", null);
}
@@ -173,8 +174,15 @@ public class NotNullVerifyingInstrumenterTest extends UsefulTestCase {
verifyCallThrowsException("@NotNull method MultipleMessages.foo2 must not return null", instance, test.getMethod("foo2"));
}
public void testMultipleAnnotations() throws Exception {
Class<?> test = prepareTest(false, "FooAnno", "BarAnno");
Object instance = test.newInstance();
verifyCallThrowsException("@FooAnno method MultipleAnnotations.foo1 must not return null", instance, test.getMethod("foo1"));
verifyCallThrowsException("@BarAnno method MultipleAnnotations.foo2 must not return null", instance, test.getMethod("foo2"));
}
public void testMalformedBytecode() throws Exception {
Class<?> testClass = prepareTest(false);
Class<?> testClass = prepareTest(false, AnnotationUtil.NOT_NULL);
verifyCallThrowsException("Argument 0 for @NotNull parameter of MalformedBytecode$NullTest2.handle must not be null", null, testClass.getMethod("main"));
}
@@ -198,10 +206,10 @@ public class NotNullVerifyingInstrumenterTest extends UsefulTestCase {
}
private Class prepareTest() throws IOException {
return prepareTest(false);
return prepareTest(false, AnnotationUtil.NOT_NULL);
}
private Class prepareTest(boolean withDebugInfo) throws IOException {
private Class prepareTest(boolean withDebugInfo, String... notNullAnnos) throws IOException {
String base = JavaTestUtil.getJavaTestDataPath() + "/compiler/notNullVerification/";
final String baseClassName = getTestName(false);
String path = base + baseClassName;
@@ -228,7 +236,7 @@ public class NotNullVerifyingInstrumenterTest extends UsefulTestCase {
FailSafeClassReader reader = new FailSafeClassReader(content, 0, content.length);
ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
modified |= NotNullVerifyingInstrumenter.processClassFile(reader, writer, null);
modified |= NotNullVerifyingInstrumenter.processClassFile(reader, writer, notNullAnnos);
byte[] instrumented = writer.toByteArray();
final String className = FileUtil.getNameWithoutExtension(fileName);
@@ -27,6 +27,7 @@ import com.intellij.psi.PsiClass;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.ui.*;
import com.intellij.ui.components.JBList;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ui.EmptyIcon;
import com.intellij.util.ui.JBUI;
import org.jetbrains.annotations.NotNull;
@@ -64,7 +65,7 @@ public class NullableNotNullDialog extends DialogWrapper {
new AnnotationsPanel("Nullable", manager.getDefaultNullable(), manager.getNullables(), NullableNotNullManager.DEFAULT_NULLABLES);
splitter.setFirstComponent(myNullablePanel.getComponent());
myNotNullPanel =
new AnnotationsPanel("NotNull", manager.getDefaultNotNull(), manager.getNotNulls(), NullableNotNullManager.DEFAULT_NOT_NULLS);
new AnnotationsPanel("NotNull", manager.getDefaultNotNull(), manager.getNotNulls(), ArrayUtil.toStringArray(manager.getPredefinedNotNulls()));
splitter.setSecondComponent(myNotNullPanel.getComponent());
splitter.setHonorComponentsMinimumSize(true);
splitter.setPreferredSize(JBUI.size(300, 400));
@@ -19,6 +19,7 @@ import com.intellij.compiler.instrumentation.FailSafeClassReader;
import com.intellij.compiler.instrumentation.InstrumentationClassFinder;
import com.intellij.compiler.notNullVerification.NotNullVerifyingInstrumenter;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
@@ -37,6 +38,7 @@ import org.jetbrains.org.objectweb.asm.Opcodes;
import java.io.File;
import java.util.Collection;
import java.util.List;
/**
* @author Eugene Zhuravlev
@@ -80,8 +82,8 @@ public class NotNullInstrumentingBuilder extends BaseInstrumentingBuilder{
InstrumentationClassFinder finder) {
try {
final ProjectDescriptor pd = context.getProjectDescriptor();
final String notNullAnnotation = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(pd.getProject()).getNotNullAnnotation();
if (NotNullVerifyingInstrumenter.processClassFile((FailSafeClassReader)reader, writer, notNullAnnotation)) {
final List<String> notNulls = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(pd.getProject()).getNotNullAnnotations();
if (NotNullVerifyingInstrumenter.processClassFile((FailSafeClassReader)reader, writer, ArrayUtil.toStringArray(notNulls))) {
return new BinaryContent(writer.toByteArray());
}
}
@@ -31,8 +31,8 @@ public interface JpsJavaCompilerConfiguration extends JpsElement {
boolean isAddNotNullAssertions();
void setAddNotNullAssertions(boolean addNotNullAssertions);
String getNotNullAnnotation();
void setNotNullAnnotation(String notNullAnnotation);
List<String> getNotNullAnnotations();
void setNotNullAnnotations(List<String> notNullAnnotations);
boolean isClearOutputDirectoryOnRebuild();
void setClearOutputDirectoryOnRebuild(boolean clearOutputDirectoryOnRebuild);
@@ -35,7 +35,7 @@ import java.util.*;
public class JpsJavaCompilerConfigurationImpl extends JpsCompositeElementBase<JpsJavaCompilerConfigurationImpl> implements JpsJavaCompilerConfiguration {
public static final JpsElementChildRole<JpsJavaCompilerConfiguration> ROLE = JpsElementChildRoleBase.create("compiler configuration");
private boolean myAddNotNullAssertions = true;
private String myNotNullAnnotation = NotNull.class.getName();
private List<String> myNotNullAnnotations = Collections.singletonList(NotNull.class.getName());
private boolean myClearOutputDirectoryOnRebuild = true;
private final JpsCompilerExcludes myCompilerExcludes = new JpsCompilerExcludesImpl();
private final List<String> myResourcePatterns = new ArrayList<String>();
@@ -67,8 +67,8 @@ public class JpsJavaCompilerConfigurationImpl extends JpsCompositeElementBase<Jp
}
@Override
public String getNotNullAnnotation() {
return myNotNullAnnotation;
public List<String> getNotNullAnnotations() {
return myNotNullAnnotations;
}
@Override
@@ -82,8 +82,8 @@ public class JpsJavaCompilerConfigurationImpl extends JpsCompositeElementBase<Jp
}
@Override
public void setNotNullAnnotation(String notNullAnnotation) {
myNotNullAnnotation = notNullAnnotation;
public void setNotNullAnnotations(List<String> notNullAnnotations) {
myNotNullAnnotations = Collections.unmodifiableList(notNullAnnotations);
}
@Override
@@ -15,6 +15,7 @@
*/
package org.jetbrains.jps.model.serialization.java.compiler;
import com.intellij.util.containers.ContainerUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.model.JpsProject;
@@ -22,13 +23,17 @@ import org.jetbrains.jps.model.java.JpsJavaExtensionService;
import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerConfiguration;
import org.jetbrains.jps.model.serialization.JpsProjectExtensionSerializer;
import java.util.Arrays;
import java.util.List;
/**
* @author vladimir.dolzhenko
*/
public class JpsJavaCompilerNotNullableSerializer extends JpsProjectExtensionSerializer {
private static final String DEFAULT_VALUE = NotNull.class.getName();
private static final String NOTNULL_ANNOTATION = "myDefaultNotNull";
private static final String VALUE = "value";
public static final List<String> DEFAULT_NOT_NULLS = Arrays.asList(
NotNull.class.getName(), "javax.annotation.Nonnull",
"edu.umd.cs.findbugs.annotations.NonNull", "android.support.annotation.NonNull"
);
public JpsJavaCompilerNotNullableSerializer() {
super("misc.xml", "NullableNotNullManager");
@@ -37,20 +42,27 @@ public class JpsJavaCompilerNotNullableSerializer extends JpsProjectExtensionSer
@Override
public void loadExtension(@NotNull JpsProject project, @NotNull Element componentTag) {
JpsJavaCompilerConfiguration configuration = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(project);
String value = DEFAULT_VALUE;
for (Element element : componentTag.getChildren("option")) {
if (NOTNULL_ANNOTATION.equals(element.getAttributeValue("name"))){
value = element.getAttributeValue(VALUE, DEFAULT_VALUE);
break;
List<String> annoNames = ContainerUtil.newArrayList();
for (Element option : componentTag.getChildren("option")) {
if ("myNotNulls".equals(option.getAttributeValue("name"))){
for (Element value : option.getChildren("value")) {
for (Element list : value.getChildren("list")) {
for (Element item : list.getChildren("item")) {
ContainerUtil.addIfNotNull(annoNames, item.getAttributeValue("itemvalue"));
}
}
}
}
}
configuration.setNotNullAnnotation(value);
if (annoNames.isEmpty()) {
annoNames.addAll(DEFAULT_NOT_NULLS);
}
configuration.setNotNullAnnotations(annoNames);
}
@Override
public void loadExtensionWithDefaultSettings(@NotNull JpsProject project) {
JpsJavaCompilerConfiguration configuration = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(project);
configuration.setNotNullAnnotation(DEFAULT_VALUE);
JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(project).setNotNullAnnotations(DEFAULT_NOT_NULLS);
}
@Override