Giter VIP home page Giter VIP logo

javapoet's People

Contributors

aleckazakova avatar auke- avatar ben-manes avatar benjamin-bader avatar caplan avatar cconroy avatar cgruber avatar christianreynoldsdr avatar danglotb avatar dependabot[bot] avatar eamonnmcmanus avatar egorand avatar galderz avatar gfx avatar gk5885 avatar jakewharton avatar jgustie avatar nightlynexus avatar octylfractal avatar ragunathjawahar avatar renovate[bot] avatar ronshapiro avatar shaishavgandhi avatar sormuras avatar sullis avatar swankjesse avatar tbroyer avatar thesurlydev avatar whiskeysierra avatar zacsweers avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

javapoet's Issues

Merge process needs tweaking

Can we do a slightly more paused merge process - merging early means that nits and style fixes needed a subsequent pull request and code we wouldn't want in gets in, even if just for a little while.

Maybe we can adopt a "ready to merge" (RTM) convention - like an author's LGTM since not all authors can self-merge.

JavaWriter 3: Blocks within methods aren't indented

If you write something like this:

  methodBody
    .addSnippet("if (%s == null) {", identifier)
    .addSnippet("throw new NullPointerException(\"Null %s\");", identifier)
    .addSnippet("}");

then you might expect that JavaWriter would automatically indent the throw statement but you would be wrong. Since we don't require people to manage indentation manually anywhere else, we shouldn't require it here either. Perhaps BlockWriter should have a method allowing you to write something like this:

  methodBody
    .addBlock("if (%s == null)", identifier)
      .addSnippet("throw new NullPointerException(\"Null %s\");", identifier);

where .addBlock would return a nested BlockWriter. Some tweaks on this idea would be needed to get the usual formatting for if/else, try/catch/finally, etc.

Consolidate MethodWriter and ConstructorWriter logic

They are exactly the same except for return type. Have the same implementation twice is bad news bears. Either refactor into a common-base class, make one extend the other, or just use MethodWriter for constructors.

Add support for nested annotations

Currently emitAnnotation will do a toString() on the value of an annotation attribute. However this becomes a nuisance if the value itself is an annotation instance with its own values.

Is there perhaps a technique (and if not please add it!) to easily define a new annotation as the value of an emitted annotation, that would function in the same way as an emitted annotation?

Documentation Support

Javadoc on type, field, method. Would be nice to have top-of-file command for license and/or generated warning as well. In its dumbest form this just need to take a string (or aggregate strings).

Interesting things here might be @param support on a ParameterWriter (VariableWriter subclass)? @throws on a ThrowsWriter? @return somewhere?

VoidTypeName should not exist

As suggested in #109, VoidTypeName suggests that void is a type, which it is not, and allows users to accidentally ask for void fields and parameters. The only place where void can appear is to specify the result of a method in MethodWriter, when the method does not return a value. As an alternative design, we could delete VoidTypeName and instead have the returnType parameter of the MethodWriter constructor be an Optional<TypeName>; or have a second constructor that omits the returnType for use when the method is void; or introduce a new supertype of TypeName called MethodReturn, with a new class VoidReturn that is also a subclass of TypeNameOrVoid.

Standardize generated field names based on convention

Currently, the field names are directly derived from the .proto files. However, it would be better if while generating the code JavaWriter could follow some conventions like:

  • Hungarian notation for fields
  • Convert underscore in proto field names to camel case

Right now, a field declared as request_id remains as request_id in Java Code and sometimes feels weird to be calling a function like request_id(21)

TypeNames.forTypeMirror intersection problem.

javax.lang.model.type.UnknownTypeException: Unknown type: java.lang.Number&java.lang.Runnable
    at javax.lang.model.util.AbstractTypeVisitor6.visitUnknown(AbstractTypeVisitor6.java:150)
    at javax.lang.model.util.AbstractTypeVisitor6.visitIntersection(AbstractTypeVisitor6.java:133)
    at com.sun.tools.javac.code.Type$IntersectionClassType.accept(Type.java:1019)
    at com.squareup.javawriter.TypeNames.forTypeMirror(TypeNames.java:52)
$ mvn -v
Apache Maven 3.2.3 (33f8c3e1027c3ddde99d3cdebad2656a31e8fdf4; 2014-08-11T13:58:10-07:00)
Maven home: /usr/local/Cellar/maven/3.2.3/libexec
Java version: 1.8.0_25, vendor: Oracle Corporation
Java home: /Library/Java/JavaVirtualMachines/jdk1.8.0_25.jdk/Contents/Home/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "mac os x", version: "10.9.5", arch: "x86_64", family: "mac"

cc @tbroyer

Stable serialVersionUID generation

A cool feature would be the stable generation of a version UID for serialization. We see other code gen implementations change this value all the time because they use things like hash functions on the string output (e.g., jOOQ) which unnecessarily churns this value.

Multi-member annotations

Currently only logic for a single value exists.

if (!memberMap.isEmpty()) {
  appendable.append('(');
  if (memberMap.size() == 1) {
    Entry<String, Writable> onlyEntry = Iterables.getOnlyElement(memberMap.entrySet());
    if (!onlyEntry.getKey().equals("value")) {
      appendable.append(onlyEntry.getKey()).append(" = ");
    }
    onlyEntry.getValue().write(appendable, context);
  }
  appendable.append(')');
}

Support Java 8 things

Some failing tests:

  @Test public void interfaceStaticMethod() throws IOException {
    javaWriter.emitPackage("com.squareup");
    javaWriter.beginType("com.squareup.Foo", "interface", EnumSet.noneOf(Modifier.class));
    javaWriter.beginMethod("Foo", "empty", EnumSet.of(STATIC));
    javaWriter.emitStatement("return new Foo() {}");
    javaWriter.endMethod();
    javaWriter.endType();
    assertCode(""
        + "package com.squareup;\n"
        + "\n"
        + "interface Foo {\n"
        + "  static Foo empty() {\n"
        + "    return new Foo() {};\n"
        + "  }\n"
        + "}\n");
  }

  @Test public void interfaceDefaultMethod() throws IOException {
    javaWriter.emitPackage("com.squareup");
    javaWriter.beginType("com.squareup.Foo", "interface", EnumSet.noneOf(Modifier.class));
    javaWriter.beginMethod("String", "asString", EnumSet.of(DEFAULT));
    javaWriter.emitStatement("return toString()");
    javaWriter.endMethod();
    javaWriter.endType();
    assertCode(""
        + "package com.squareup;\n"
        + "\n"
        + "interface Foo {\n"
        + "  default String asString() {\n"
        + "    return toString();\n"
        + "  }\n"
        + "}\n");
  }

Imports sometimes incorrect when inheriting nested type of same name

If you are generating a subclass of a class like this...

// Parent.java
class Parent {
  static class Optional {}
}

// Generated Child.java
class Child extends Parent {
  java.util.Optional<String> optionalString() {...}
}

...then it is not correct to import java.util.Optional and abbreviate to "Optional optionalString()", because the inherited nested Optional takes precedence over the import statement. Since JavaWriter typically doesn't know anything about Parent in this case, there should be some way of telling it to fully-qualify a type even if it would otherwise be inclined to import it.

This is an actual case that occurs with AutoValue in code at Google. (AutoValue doesn't use JavaWriter and can't as long as this bug remains.)

JavaWriter 3: No way to specify superclass

TypeWriter has a field Optional supertype but no way to set it. Also, it probably belongs to ClassWriter rather than TypeWriter, since other kinds of types don't have settable supertypes.

Add throws clause to beginMethod

I'd like to be able to add throws SomeException clauses to method declarations. I've been poking around and didn't see this functionality. Do you guys not do this at Square (you must be emiting control flows for exceptions)?

Empty method bodies appear abstract.

ClassWriter cw = ClassWriter.forClassName(ClassName.bestGuessFromString("example.Test"));
cw.addMethod(VoidName.VOID, "test");
System.out.println(cw);
package example;

class Test {
  void test();
}

This is unfortunate, unexpected behavior. Only if the method is declared abstract should this behavior happen.

Interface methods should not emit public, abstract

Not quite sure the right approach to take with this. We can either propagate these implementation details downward into Modifiable or switch to private fields with public getters (e.g., Set<Modifier> modifiers()) which can be overridden to return subsets.

Thoughtful ordering of members

Right now static methods are emitted below constructors.

Seems like the only logical grouping we should make. There are other one's in practice (public static methods before lesser scoped static methods, public instance methods before lesser scoped instance methods, etc.) but I don't think they should be addressed at this time (if ever).

Enhancement: deferable writing

If JavaWriter provided a StringBuilder that could be written to instead of writing to the Writer, then it could reduce the amount of loops I need to generate code. For example, if I have a list of "model"s. I need to generate a field for each model, and also an if-else-if-else block for each model. Ideally I could iterate the model list once, but if you have to write the lines sequentially through the JavaWriter, then the loop has to be repeated in the different locations in the "file".

I have a workaround that helps in some cases, which is I create a StringBuilder and build into it, but this doesn't resolve all situations, because the JavaWriter doesn't allow arbitrary String insertion.

To be verbose, I have an idea for adding a class that is essentially a StringBuilder that can't be constructed outside of JavaWriter, but can be passed in place of a Writer, allowing chunks of code to be generated in it. Then, the StringBuilder-like class can be written by the JavaWriter where the block should be in the final generated file. The library doesn't manage the StringBuilder-like class, only an agreement that the String in it is built to be valid Java. I'm curious if the library is interested in such a feature.

Better Error Messages for emitMethod()

Writing Something like this:

  javaWriter.beginMethod("void", "save", Sets.newHashSet(Modifier.PUBLIC), "ContentValues contentValues");

Will thrown an ArrayIndexOutOfBoundsException instead of checking to ensure the parameters are perfectly even. May I suggest a throwable with a better message?

Immutables, builders & ClassSpec.builder("Taco")

ClassSpec c = ClassSpec.builder("Taco")   // proto-like pattern
   .addMethod(MethodSpec.builder("toString")
       .addAnnotation(Override.class)
       .modifiers(PUBLIC, FINAL)
       .returns(String.class)
       .code("return \"taco\"")
       .build())
   .addMethod(MethodSpec.builderOverriding(executableElement)
       .addSnippet(Snippet.format("return 0;"))
       .build())
   .build()

Language level?

I'd prefer to write this using Java 7 since 6 is EOL'd for a while now. I know this will be used in a variety of environments, though, so what do others think?

For example, not being able to use java.nio.file.Path and try-with-resources just is no fun!

@gk5885 @tbroyer @cgruber

Static imports

public JavaWriter addStaticImport(Class<?> cls, String methodName) { }
private final SetMultimap<ClassName, String> staticImports = LinkedHashMultimap.create();

Should be a bit more straightforward to emit since the logic for actually choosing which imports only applies to the current and parent contexts in the same file. A much smaller scope than regular import resolution.

Evaluate source tree writer

In both v3 and v2 knowledge of how contents were being emitted leaks around too far for my liking. In almost all cases of writing you have a destination folder and want normal Java folder and file naming semantics inferred from package and class name.

The one potential exception to this rule is annotation processors which go through the Filer. I don't think we necessarily need to cover that use case, but if it can be done easily that would be a nice touch.

Sensible wrapping, where appropriate

There are parts of code to which we can apply sensible wrapping. Right column break to be configured on JavaWriter.

Candidates include:

  • Class declaration (extends, interfaces)
  • Field initializer (if length exceeds wrap&indent initializer)
  • Method declaration (params, exceptions)

End of Line Comment Limited Use

The end-of-line comment has little value with it's current behavior.

w.emitStatement("foo()");
w.emitEndOfLineComment("Call foo!");

produces something like:

    ...
    foo();
// Call foo!
    ...

Its Javadoc is also wrong.

Support javax.lang.model.element.Modifier

java.lang.reflect.Modifier is pretty gross and makes for a bunch of code littered with ints and ORs. In the land of annotation processing we have a better alternative: http://docs.oracle.com/javase/6/docs/api/javax/lang/model/element/Modifier.html

I'd like to add versions of all of the JavaWriter methods that take Set instead of int. Then, ideally we'd phase out the int methods at some point in the future.

Since it's a fair bit of work, I wanted some consensus before bothering to do all of the work. Any objections?

Should we add LambdaWriter support?

Lambdas are interesting syntactical elements. Should we have first-party support for them or just rely on normal Snippet behavior for them?

A first-party type for supporting lambdas would deal with:

  • Choosing whether or not argument parenthesis should be emitted.
  • Comma-separating the argument list.
  • Type declarations in arguments (e.g., (Runnable r) -> r.run()).
  • Emitting the arrow.
  • Choosing whether or not braces are emitted.

JavaWriter 3: Can't generate or reference classes in the default package

I'm not sure how important it is to be able to generate classes in the default package, but it currently doesn't work because of a couple of issues in JavaWriter.java: it should not generate a package statement in this case, and it should consider className.packageName().isEmpty() as an additional reason not to import className.

Add support for anonymous inner classes

Currently it doesn't look like there is an easy way to write

MyInterface foo = new MyInterface() {

   @Override
   public void bar() {
      // do something awesome
   }
};

A possible api would be

beginAnonymousInnerClass(String kind);

beginAnonymousInnerClass(String fieldType, String fieldName, Set<Modifier> modifiers, String kind);

endAnonymousInnerClass();

The extended begin method would result in

modifiers fieldType fieldName = new kind() {

Consider BlockWriter emitting braces.

I think BlockWriter might be more useful if it was in control if emitting braces. This is a trivial change for methods and ctors, but I think the value is in user snippets as well.

For example,

if (thing) %s

Could take a BlockWriter and emit

if (thing) {
  doSomething();
  doSomethingElse();
  return true;
}

This would work well for switch as well:

case "hello": %s
case "hi": %s

Could emit:

case "hello": {
  String name = getName();
  return "Hello, " + name;
}
case "hi": {
  String name = getName();
  return "Hi, " + name;
}

Version 3.0 Working Spec

This issue will serve as a working space for what a potential version 3.0 would look like with a new, more dynamic, and more powerful API.

High-Level Goals

  • The ability to defer type compression (imports) until emission.
  • Distinct code blocks as objects for composition.
  • And more, probably...

Deferred Type Compression

Currently, type compression via imports requires knowledge of all types up before the body of the file. In practice, this usually requires an awkward two-pass approach where you determine the imports based on a pass of dynamic contents and then emit the body based on a second pass.

The goal of this is to always emit fully-qualified types from the API and rely on a post-compression phase for emitting imports.

There are multiple ways to approach this. A non-exhaustive list:

  • Type location-aware parsing of code statements combined with type parameters.
  • Method which wraps a type in a token that can later be replaced.
  • Code blocks which are aware of which types they contain. (see below)

Code Block Objects

Objects which represents pieces of code lend themselves naturally to writing emission code in Java. The wins should hopefully be fairly obvious.

There is a potential for API explosion here to cover the diversity of the Java language. A potential also exists for adding an unacceptable amount of boilerplate to the API.

Add support for annotated method parameters.

Which of the following API design is better on interface and abstract methods that will support annotated parameters?

javaWriter.beginMethodSignature(returnType, methodName, modifiers);
javaWriter.emitAnnotation(annotationType);
javaWriter.emitParam(paramType, paramName);
javaWriter.endMethodSignature();

or

javaWriter.beginMethodSignature(returnType, methodName, modifiers);
javaWriter.emitAnnotation(annotationType);
javaWriter.emitParam(paramType, paramName);
javaWriter.endMethodSignature();
javaWriter.endMethod(); // <== Regardless of the type definition or modifier??

Can't use annotation @Param

Hi,

i use eclipse w/o gradle or maven. I addede groundy as library and compiler as annotation processor to the project. Everything works right except @param.

when i try to use @onProgress or @para i get error.
as i understand compiler use annotation Param but it doesn't present in his classpath.
i tried to add it to the jar but eclipse gets crash.

i can't understand why because in my own processor(AnnotatedSQL project) i use annotaions in compiler without problems

Error:

Errors occurred during the build.
Errors running builder 'Java Builder' on project .
com/telly/groundy/annotations/Param

Thanks,
Gennadiy

address simple name collisions in compressType

When there exists the same named simple type in the package of the class being written and also imports, parameterized types should retain the package.

Failing test case below:

@Test public void compressSimpleNameCollisionInSamePackage() throws IOException {
    javaWriter.emitPackage("denominator");
    javaWriter.emitImports("javax.inject.Provider", "dagger.internal.Binding");
    String actual = javaWriter.compressType("dagger.internal.Binding<denominator.Provider>");
    assertThat(actual).isEqualTo("Binding<denominator.Provider>");
  }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.