danielnorberg / auto-matter Goto Github PK
View Code? Open in Web Editor NEWMinimal value types for Java
License: Apache License 2.0
Minimal value types for Java
License: Apache License 2.0
As methods without the get
prefix are not considered properties per the JavaBean spec, Bean Validation constraint annotations (e.g. @NotNull
, @NotEmpty
, etc) are not by vanilla Bean Validation frameworks.
I.e., unless fields are explicitly named getFoo
and getBar
etc, niceties like Dropwizard Validation does not work.
Hi, I think I've found a case in which the generated builder is not as it should.
If I have a record like such
public Record(int a, @Nullable String b) {}
A builder which asserts non-nulls on 'b' will be created. I cannot use Optional<String>
instead because Optional is not Serializable and I need my record to be so.
Any thoughts on introducing a getFields
method to automatter objects? Would love to be able to iterate through an Automatter Object's fields. I have a usecase to check that at least one field is populated in the object and right now, I'm forced to manually check every field to get that.
...
Running io.norberg.automatter.jackson.AutoMatterModuleTest
Tests run: 7, Failures: 0, Errors: 5, Skipped: 0, Time elapsed: 0.277 sec <<< FAILURE!
testPublicInner(io.norberg.automatter.jackson.AutoMatterModuleTest) Time elapsed: 0.208 sec <<< ERROR!
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "foobar" (class io.norberg.automatter.jackson.PublicBarBuilder$Value), not marked as ignorable (4 known properties: "a", "b", "aCamelCaseField", "isReallyFoobar"])
at [Source: {"a":17,"b":"foobar","aCamelCaseField":true,"foobar":false}; line: 1, column: 60] (through reference chain: io.norberg.automatter.jackson.Value["foobar"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:62)
at com.fasterxml.jackson.databind.DeserializationContext.reportUnknownProperty(DeserializationContext.java:855)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1083)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1389)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperties(BeanDeserializerBase.java:1343)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:455)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1123)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:298)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:133)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3788)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2779)
at io.norberg.automatter.jackson.AutoMatterModuleTest.testPublicInner(AutoMatterModuleTest.java:63)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
...
E.g.
interface Foo {
List<String> foos();
}
@AutoMatter
interface Bar extends Foo {
List<String> foos();
}
Would something like this make sense?
@AutoMatter
public interface Room {
@Default(value = "foo")
String id();
}
Currently value-type inheritance works great, but there's no good way to copy data between an instance of a value type to one that inherits from it.
For example:
@AutoMatter
public interface FooValue {
String foo();
}
@AutoMatter
public interface BarValue extends FooValue {
String bar();
}
// If we have...
FooValue foo = new FooValueBuilder()
.foo("Hello ")
.build();
// It would be great to be able to do this:
BarValue bar = BarValueBuilder.from(foo)
.bar("world!")
.build();
// Or maybe this, to support inheriting from more than one interface:
BarValue bar2 = new BarValueBuilder()
.include(foo) // better names could be ".import()" or ".copy()"
.bar("world!")
.build();
This could probably be simplified if you only include support for ancestor interfaces which are also annotated with @AutoMatter
.
The above example is a bit contrived, of course, but you could see how this would get to be a huge pain if the base interface had a lot of fields.
Let's say I want a model matching the following Json:
{
"result": "OK"
}
I would create an AutoMatter class like this:
@AutoMatter
public interface RestResult {
String result();
}
The current version of AutoMatter would generate the following hashCode()
function:
@Override
public int hashCode() {
int result = 1;
long temp;
result = 31 * result + (result != null ? result.hashCode() : 0);
return result;
}
This would not compile because there is a conflict between the ivar result
and the field with the same name.
The proper code should be :
@Override
public int hashCode() {
int result = 1;
long temp;
result = 31 * result + (this.result != null ? this.result.hashCode() : 0);
return result;
}
So the library would need to add this.
when referencing fields to avoid conflicts with method's variables.
I've noticed that in all the versions since 0.22 there was a change behaviour which causes a NullPointerExcection.
Step to reproduce:
from()
methodExpected behaviour: copy of the builder is created (with nullable collection set to null)
Actual behaviour: NPE is thrown due to nullable collection being unset
Earlier version - 0.21 - worked as expected.
Builder:
@AutoMatter
public interface Foobar {
@Nullable
List<String> fruits();
}
Usage:
// regular builder usage with nullable works fine
var builder = new FoobarBuilder().build();
assert builder.fruits() == null;
// copying builder works as expected if nullable field is set on the source builder
var builderWithNullableSet = new FoobarBuilder().fruits("banana");
var builderCopy = FoobarBuilder.from(builderWithNullableSet);
assert builderCopy.fruits().equals(List.of("banana"));
// copying builder throws NPE if nullable collection not set on the source builder
var builderWithNullableUnset = new FoobarBuilder();
// throws NPE: Cannot invoke "java.util.Collection.toArray()" because "c" is null
FoobarBuilder.from(builderWithNullableUnset);
I believe that this behaviour was caused by this change (Fix Spotbugs complaints):
#184
As it removed extra null checks - e.g. the generated code in builders changed from:
this.foos = (v.foos() == null) ? null : new ArrayList<T>(v.foos());
to
this.foos = new ArrayList<T>(v.foos());
It may as well be that I missed some context and I am not right about it, but it looks to me like a bug.
Hello,
I was wondering whether anyone would have any ideas on how to declare and gson deserialise an entity with a field named "private"?
Thanks!
This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.
These updates are currently rate-limited. Click on a checkbox below to force their creation now.
These updates have all been created already. Click a checkbox below to force a retry/rebase of any.
.circleci/config.yml
cimg/openjdk 17.0.9
cimg/openjdk 17.0.9
cimg/openjdk 17.0.9
annotation/pom.xml
bom/pom.xml
dependencies/pom.xml
junit:junit 4.13.2
com.github.javaparser:javaparser-core 3.25.6
com.squareup:javapoet 1.13.0
com.google.code.gson:gson 2.10.1
com.google.code.findbugs:jsr305 3.0.2
com.google.guava:guava 31.1-jre
com.google.truth:truth 1.1.5
com.google.testing.compile:compile-testing 0.19
com.google.auto:auto-common 1.2.2
com.google.errorprone:error_prone_annotations 2.23.0
org.checkerframework:checker-qual 3.40.0
org.hamcrest:hamcrest 2.2
org.hamcrest:hamcrest-library 2.2
org.hamcrest:hamcrest-core 2.2
example/pom.xml
org.apache.maven.plugins:maven-compiler-plugin 3.11.0
com.google.errorprone:error_prone_core 2.23.0
org.apache.maven.plugins:maven-compiler-plugin 3.11.0
com.google.errorprone:error_prone_core 2.23.0
org.apache.maven.plugins:maven-javadoc-plugin 3.6.2
com.github.spotbugs:spotbugs-maven-plugin 4.8.1.0
com.github.spotbugs:spotbugs 4.8.1
com.fasterxml.jackson:jackson-bom 2.15.3
com.google.code.gson:gson 2.10.1
com.google.guava:guava 31.1-jre
com.google.code.findbugs:jsr305 3.0.2
gson/pom.xml
jackson/pom.xml
pom.xml
com.fasterxml.jackson:jackson-bom 2.15.3
com.google.auto.service:auto-service 1.1.1
com.google.auto.service:auto-service-annotations 1.1.1
org.apache.maven.plugins:maven-dependency-plugin 3.6.1
org.apache.maven.plugins:maven-jar-plugin 3.3.0
org.apache.maven.plugins:maven-surefire-plugin 2.22.2
com.spotify.fmt:fmt-maven-plugin 2.21.1
org.apache.maven.plugins:maven-compiler-plugin 3.11.0
org.sonatype.plugins:nexus-staging-maven-plugin 1.6.13
org.apache.maven.plugins:maven-release-plugin 2.5.3
org.apache.maven.scm:maven-scm-provider-gitexe 1.13.0
org.apache.maven.scm:maven-scm-api 1.13.0
org.apache.maven.plugins:maven-enforcer-plugin 3.4.1
org.apache.maven.plugins:maven-source-plugin 3.3.0
org.apache.maven.plugins:maven-javadoc-plugin 3.6.2
org.apache.maven.plugins:maven-gpg-plugin 3.1.0
org.jacoco:jacoco-maven-plugin 0.8.11
com.google.auto.service:auto-service 1.1.1
processor/pom.xml
record-test/pom.xml
.mvn/wrapper/maven-wrapper.properties
maven 3.9.5
maven-wrapper 3.2.0
E.g. <A extends SomeType> List<A> myfield();
Hi,
I would like to contribute minor improvements to this library. Do you have any plan for the futur for this project ? Do you have any guide for contributing to the project ?
For example I just added @Nullable
to builder setters parameters if the value is defined as @Nullable
in the interface : vincentbrison@2bfa2b9
I think it would be a nice feature since the developer would directly know if a field can be null or no when building it. Can I send you a PR for it ?
Found this the other day when I tried to parse a 2-element JSON list into a Guava range using a custom @JsonCreator
Jackson annotation on a AutoMatter interface. The cause seems to be that the module always treats the constructor of the generated value type as the creator method.
Testcase:
public class JsonCreatorExample {
@AutoMatter
public interface WithJsonCreator {
int val();
@JsonCreator static WithJsonCreator of(final int val) {
return new WithJsonCreatorBuilder().val(val+1).build();
}
}
public static void main(final String... args) throws IOException {
final WithJsonCreator c = new ObjectMapper()
.registerModule(new AutoMatterModule())
.readValue("{ \"val\": 3 }", WithJsonCreator.class);
System.out.println(c.val());
}
}
@AutoMatter
interface SuperType {
@JsonProperty
String field();
@JsonProperty
String overrideMe();
}
@AutoMatter
interface SubType extends SuperType {
@Override
@JsonProperty
default String overrideMe() {
return "overridden hardcoded value";
}
}
which generates the following
final class SubTypeBuilder {
private String field;
private SubTypeBuilder(SuperType v) {
this.overrideMe= v.overrideMe();
}
....
}
where overrideMe
is not a class variable because it was overridden by a default
method thus causing a compile error
tried fixing this locally and had success by checking whether the method is default here: https://github.com/danielnorberg/auto-matter/blob/master/processor/src/main/java/io/norberg/automatter/processor/AutoMatterProcessor.java#L411-L415
and skipping if it was, happy to open a PR if it helps
I noticed this in one of my own projects where I was using the latest maven-compiler-plugin 3.3, but you can reproduce it in auto-matter as well.
$ git diff
diff --git a/pom.xml b/pom.xml
index eee9221..b31cb35 100644
--- a/pom.xml
+++ b/pom.xml
@@ -57,7 +57,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
- <version>2.5.1</version>
+ <version>3.3</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
$ mvn compile
...
[INFO] BUILD SUCCESS
First time works.
$ java -cp example/target/classes io.norberg.automatter.example.SimpleExample
bar: 17
foo: hello world
foobar: Foobar{foo=hello world, bar=17}
modified: Foobar{foo=hello world, bar=18}
Compiling a second time breaks
$ mvn compile
...
[INFO] --- maven-compiler-plugin:3.3:compile (default-compile) @ auto-matter-example ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 12 source files to /var/tmp/auto-matter/example/target/classes
An exception has occurred in the compiler (1.8.0_40). Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport) after checking the Bug Parade for duplicates. Include your program and the following diagnostic in your report. Thank you.
java.lang.IllegalStateException: endPosTable already set
at com.sun.tools.javac.util.DiagnosticSource.setEndPosTable(DiagnosticSource.java:136)
at com.sun.tools.javac.util.Log.setEndPosTable(Log.java:350)
...
https://gist.github.com/jooon/386352b9f922d39dda78
Is this an actual java bug or a problem with maven-compiler-plugin or auto-matter?
Documentation says it's possible to add behavior to a value type and give an example using an interface definition.
I tried to do the same using a record definition without success. Let's use this dumb example:
@AutoMatter
public record IntString(String asString) {
int asInt() {
return Integer.parseInt( asString() );
}
}
AutoMatter generates following code:
private IntStringBuilder(IntString v) {
this.asInt = v.asInt();
this.asString = v.asString();
}
private IntStringBuilder(IntStringBuilder v) {
this.asInt = v.asInt();
this.asString = v.asString();
}
public IntString build() {
if (asString == null) {
throw new NullPointerException("asString");
}
return new IntString(asInt, asString);
}
I think that any methods which is not a record component must be ignored by the builder.
It seems that auto-matter pulls in the h2 database through modeshape-common. Modeshape is only used to get the singularize
method out of an Inflector
.
It would be nice to avoid pulling a full database and modeshape itself for that. As an alternative, maybe there is a lighter-weight inflector from another library or alternatively this Inflector
could be vendored in?
Thanks!
Allow something like this:
@AutoMatter
class Foo<T> {
// fields ...
}
There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.
Error type: Cannot find preset's package (github>whitesource/merge-confidence:beta)
Hi,
Let's say I have the following classes :
@AutoMatter
public interface Foo<T> {
List<T> foos();
}
and
@AutoMatter
public interface Bar extends Foo<Integer> {
}
The generated BarBuilder
is manipulating List<? extends T>
instead of List<? extends Integer>
, resulting in building error.
I suppose this is not intended ?
BR
Note: Running project can be found here: https://github.com/andersonvom/auto-matter-bug
In the following setup
<!-- pom.xml -->
<dependency>
<groupId>io.norberg</groupId>
<artifactId>auto-matter</artifactId>
<version>0.15.3</version>
</dependency>
<dependency>
<groupId>io.norberg</groupId>
<artifactId>auto-matter-jackson</artifactId>
<version>0.15.3</version>
</dependency>
// Foobar.java
@AutoMatter
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
interface Foobar {
@Nullable String foo();
Optional<String> bar();
}
The optional attribute Optional<String> bar()
gets serialized as "bar":{"empty":false,"present":true}}
and throw the following exception when it is deserialized:
ObjectMapper objectMapper = new ObjectMapper().registerModule(new AutoMatterModule());
Foobar foobar = new FoobarBuilder().foo("foo").bar("bar").build();
String json = objectMapper.writeValueAsString(foobar);
System.out.println("serialized: " + json);
// throws com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException:
// Unrecognized field "empty" (class java.util.Optional),
// not marked as ignorable (0 known properties: ])
Foobar parsed = objectMapper.readValue(json, Foobar.class);
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "empty" (class java.util.Optional), not marked as ignorable (0 known properties: ])
at [Source: {"foo":"foo","bar":{"empty":false,"present":true}}; line: 1, column: 34] (through reference chain: com.mycompany.app.FoobarBuilder$Value["bar"]->java.util.Optional["empty"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:62)
at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:834)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1093)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1489)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1467)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:282)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:140)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:504)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:511)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:400)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1191)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:314)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:148)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3814)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2858)
at com.mycompany.app.AppTest.testApp(AppTest.java:29)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.mockito.internal.runners.DefaultInternalRunner$1$1.evaluate(DefaultInternalRunner.java:44)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:74)
at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:80)
at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39)
at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:163)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Am I doing something wrong or is this an actual bug?
Would it be possible to add a build method or another method on the builderobject that populates all not null values with dummy values. This would be useful when writing unit tests and reduce boilerplate code when you only care for some fields.
PR to demonstrate issue: #75
As we talked about in the Slack channel...
When I wanted to make a generic type interface with automatter and have a field type that's nested with Optional and List, the generated code is incorrect in handling the types.
The issue I had was the following interface definition
@AutoMatter
public interface ResponseAndEvents<T> {
Response response();
Optional<List<T>> eventsMaybe()
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.