Skip to content

Commit

Permalink
#638 making encodings to work with @default @derived
Browse files Browse the repository at this point in the history
+ massaging
  • Loading branch information
elucash committed Jan 2, 2018
1 parent f838ac1 commit ef1e85a
Show file tree
Hide file tree
Showing 18 changed files with 455 additions and 143 deletions.
19 changes: 17 additions & 2 deletions encode/src/org/immutables/encode/Encoding.java
Expand Up @@ -110,6 +110,19 @@
@Retention(RetentionPolicy.SOURCE)
public @interface Build {}

/**
* Template method for internal purposes that describes how to ask builder if an attribute was
* initialized. This must be a boolean-returning no-arg accessor method on a builder.
* Implementation will always be private regardless if provided method is defined as private or
* not. If builder encoding is not defined (i.e. no {@code Encoding.Builder}), the generator will
* infer this as a a null check, but if builder encoding is defined with no such {@code IsInit}
* provided, then encoding will be unable to generate
* code for instantiations of {@code Value.Default} or {@code Value.Derived} attributes.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface IsInit {}

/**
* Many elements (but not all) supports customized naming patterns.
* Use single asterisk symbol in a name to denote a placeholder where attribute name would be
Expand All @@ -128,8 +141,10 @@
* As an alternative to specifying a pattern, you may want to reuse {@link #standard()} naming.
* <p>
* <em>
* Please note, that with customized naming it is possible (but in general, not recommended) to put
* constant naming (without {@code "*"} placeholder) on elements. But when you do this it can result
* Please note, that with customized naming it is possible (but in general, not recommended) to
* put
* constant naming (without {@code "*"} placeholder) on elements. But when you do this it can
* result
* in name clashes in generated code.
* </em>
* @see #depluralize()
Expand Down
30 changes: 22 additions & 8 deletions generator/src/org/immutables/generator/Output.java
Expand Up @@ -24,6 +24,7 @@
import com.google.common.base.Throwables;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import com.google.common.collect.Sets;
import com.google.common.io.CharSink;
import com.google.common.io.CharSource;
Expand All @@ -42,6 +43,7 @@
import javax.annotation.processing.Filer;
import javax.annotation.processing.FilerException;
import javax.annotation.processing.Messager;
import javax.lang.model.element.Element;
import javax.tools.Diagnostic;
import javax.tools.Diagnostic.Kind;
import javax.tools.FileObject;
Expand All @@ -57,8 +59,17 @@ public final class Output {
@Override
@Nullable
public Invokable invoke(Invokation invokation, Object... parameters) {
String message = CharMatcher.WHITESPACE.trimFrom(parameters[0].toString());
StaticEnvironment.processing().getMessager().printMessage(Diagnostic.Kind.ERROR, message);
Messager messager = StaticEnvironment.processing().getMessager();
String message = CharMatcher.WHITESPACE.trimFrom(parameters[parameters.length - 1].toString());
Element element = (Element) Iterators.find(
Iterators.forArray(parameters),
Predicates.instanceOf(Element.class),
null);
if (element != null) {
messager.printMessage(Diagnostic.Kind.ERROR, message, element);
} else {
messager.printMessage(Diagnostic.Kind.ERROR, message);
}
return null;
}
};
Expand Down Expand Up @@ -296,11 +307,13 @@ void complete() {
if (identicalFileIsAlreadyGenerated(sourceCode)) {
getMessager().printMessage(Kind.MANDATORY_WARNING, "Regenerated file with the same content: " + key);
} else {
getMessager().printMessage(Kind.ERROR, String.format(
"Generated source file name colission. Attempt to overwrite already generated file: %s, %s."
+ " If this happens when using @Value.Immutable on same-named nested classes in the same package,"
+ " use can use @Value.Enclosing annotation to provide some sort of namespacing",
key, ex));
getMessager().printMessage(Kind.ERROR,
String.format(
"Generated source file name colission. Attempt to overwrite already generated file: %s, %s."
+ " If this happens when using @Value.Immutable on same-named nested classes in the same package,"
+ " use can use @Value.Enclosing annotation to provide some sort of namespacing",
key,
ex));
}
} catch (IOException ex) {
throw Throwables.propagate(ex);
Expand All @@ -317,7 +330,8 @@ private boolean identicalFileIsAlreadyGenerated(CharSequence sourceCode) {
public Reader openStream() throws IOException {
return getFiler()
.getResource(StandardLocation.SOURCE_OUTPUT,
"", packagePath + filename)
"",
packagePath + filename)
.openReader(true);
}
}.read();
Expand Down
Expand Up @@ -15,13 +15,15 @@
*/
package org.immutables.fixture.encoding.defs;

import java.util.Objects;
import java.util.OptionalDouble;
import org.immutables.encode.Encoding;
import org.immutables.encode.Encoding.StandardNaming;

@Encoding
class CompactOptionalDouble {
@Encoding.Impl(virtual = true)
private OptionalDouble opt;
private final OptionalDouble opt = OptionalDouble.empty();

private final double value = opt.orElse(0);
private final boolean present = opt.isPresent();
Expand All @@ -40,4 +42,31 @@ OptionalDouble get() {
? OptionalDouble.of(value)
: OptionalDouble.empty();
}

@Encoding.Builder
static final class Builder {
private OptionalDouble builder = OptionalDouble.empty();

@Encoding.Naming(standard = StandardNaming.INIT)
@Encoding.Init
void set(double value) {
this.builder = OptionalDouble.of(value);
}

@Encoding.Copy
@Encoding.Init
void setOpt(OptionalDouble value) {
this.builder = Objects.requireNonNull(value);
}

@Encoding.IsInit
boolean isSet() {
return builder.isPresent();
}

@Encoding.Build
OptionalDouble build() {
return this.builder;
}
}
}
@@ -0,0 +1,79 @@
/*
Copyright 2018 Immutables Authors and Contributors
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 org.immutables.fixture.encoding;

import java.util.OptionalDouble;
import java.util.OptionalInt;
import org.immutables.fixture.encoding.defs.CompactOptionalDoubleEnabled;
import org.immutables.fixture.encoding.defs.CompactOptionalIntEnabled;
import org.immutables.fixture.encoding.defs.VoidEncodingEnabled;
import org.immutables.value.Value;

@CompactOptionalIntEnabled
@CompactOptionalDoubleEnabled
@Value.Immutable
public abstract class DefaultDerivedEncs {
abstract OptionalInt a();

public @Value.Default OptionalInt i() {
return OptionalInt.empty();
}

public @Value.Derived OptionalDouble d() {
return OptionalDouble.of(0.5);
}

public @Value.Default Void v() {
return null;
}

public @Value.Derived Void dv() {
return null;
}
}

@CompactOptionalDoubleEnabled
@CompactOptionalIntEnabled
@VoidEncodingEnabled
@Value.Immutable(singleton = true)
interface DefaultSomeMore {
OptionalDouble f();

default @Value.Derived OptionalInt i() {
return OptionalInt.of(1);
}

default @Value.Default OptionalDouble d() {
return OptionalDouble.empty();
}
}

@CompactOptionalDoubleEnabled
@CompactOptionalIntEnabled
@Value.Immutable(builder = false)
@Value.Style(privateNoargConstructor = true)
interface DefaultBuilderless {
@Value.Parameter
OptionalDouble f();

default @Value.Derived OptionalInt i() {
return OptionalInt.of(1);
}

default @Value.Default OptionalDouble d() {
return OptionalDouble.empty();
}
}
@@ -1,3 +1,18 @@
/*
Copyright 2018 Immutables Authors and Contributors
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 org.immutables.fixture.encoding;

import com.fasterxml.jackson.databind.annotation.JsonSerialize;
Expand All @@ -9,5 +24,5 @@
@Value.Immutable
@MutableListEncodingEnabled
public interface FooMutableList {
List<String> getInnerFoo();
List<String> getFoo();
}
@@ -1,15 +1,17 @@
package org.immutables.value.processor;

import com.google.common.base.Function;
import org.immutables.generator.AbstractTemplate;
import org.immutables.generator.Generator;
import org.immutables.generator.Templates;
import org.immutables.value.processor.meta.HasStyleInfo;
import org.immutables.value.processor.meta.LongBits;
import org.immutables.value.processor.meta.ObscureFeatures;
import org.immutables.value.processor.meta.Proto.DeclaringPackage;
import org.immutables.value.processor.meta.StyleInfo;
import org.immutables.value.processor.meta.UnshadeGuava;
import org.immutables.value.processor.meta.ValueAttribute;
import org.immutables.value.processor.meta.ValueType;
import org.immutables.value.processor.meta.Proto.DeclaringPackage;

/** Groups typedefs and useful utilities. */
public abstract class AbstractValuesTemplate extends AbstractTemplate {
Expand All @@ -35,6 +37,13 @@ public abstract class AbstractValuesTemplate extends AbstractTemplate {

protected final LongBits longsFor = new LongBits();

protected final Function<Object, String> asDiamond = new Function<Object, String>() {
@Override
public String apply(Object input) {
return ObscureFeatures.noDiamonds() ? ("<" + input + ">") : "<>";
}
};

protected final Templates.Binary<HasStyleInfo, String, Boolean> allowsClasspathAnnotation =
new Templates.Binary<HasStyleInfo, String, Boolean>() {
@Override
Expand Down

0 comments on commit ef1e85a

Please sign in to comment.