mirror of
https://gitee.com/dcren/initializr.git
synced 2025-04-05 17:38:06 +08:00
Add language abstraction
This commit adds a `Language` on the JVM abstraction with well known concepts such as `Annotation`, `Parameter`, `CompilationUnit` and `TypeDeclaration` that concrete language implementations can reuse. See gh-813 Co-authored-by: Stephane Nicoll <snicoll@pivotal.io>
This commit is contained in:
parent
b6e675de40
commit
77bb7eb3ac
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* 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 io.spring.initializr.generator.language;
|
||||
|
||||
/**
|
||||
* Base {@link Language} implementation.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public abstract class AbstractLanguage implements Language {
|
||||
|
||||
private final String id;
|
||||
|
||||
private final String jvmVersion;
|
||||
|
||||
protected AbstractLanguage(String id, String jvmVersion) {
|
||||
this.id = id;
|
||||
this.jvmVersion = (jvmVersion != null) ? jvmVersion : DEFAULT_JVM_VERSION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String id() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String jvmVersion() {
|
||||
return this.jvmVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return id();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* 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 io.spring.initializr.generator.language;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A representation of something that can be annotated.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public interface Annotatable {
|
||||
|
||||
void annotate(Annotation annotation);
|
||||
|
||||
List<Annotation> getAnnotations();
|
||||
|
||||
}
|
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* 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 io.spring.initializr.generator.language;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* An annotation.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public final class Annotation {
|
||||
|
||||
private final String name;
|
||||
|
||||
private final List<Attribute> attributes;
|
||||
|
||||
private Annotation(Builder builder) {
|
||||
this.name = builder.name;
|
||||
this.attributes = Collections
|
||||
.unmodifiableList(new ArrayList<>(builder.attributes.values()));
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public List<Attribute> getAttributes() {
|
||||
return this.attributes;
|
||||
}
|
||||
|
||||
public static Annotation name(String name) {
|
||||
return name(name, null);
|
||||
}
|
||||
|
||||
public static Annotation name(String name, Consumer<Builder> annotation) {
|
||||
Builder builder = new Builder(name);
|
||||
if (annotation != null) {
|
||||
annotation.accept(builder);
|
||||
}
|
||||
return new Annotation(builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for creating an {@link Annotation}.
|
||||
*/
|
||||
public static final class Builder {
|
||||
|
||||
private final String name;
|
||||
|
||||
private final Map<String, Attribute> attributes = new LinkedHashMap<>();
|
||||
|
||||
private Builder(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Builder attribute(String name, Class<?> type, String... values) {
|
||||
this.attributes.put(name, new Attribute(name, type, values));
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Define an attribute of an annotation.
|
||||
*/
|
||||
public static final class Attribute {
|
||||
|
||||
private final String name;
|
||||
|
||||
private final Class<?> type;
|
||||
|
||||
private final List<String> values;
|
||||
|
||||
private Attribute(String name, Class<?> type, String... values) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.values = Arrays.asList(values);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public Class<?> getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public List<String> getValues() {
|
||||
return this.values;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* 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 io.spring.initializr.generator.language;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A compilation unit that represents an individual source file.
|
||||
*
|
||||
* @param <T> the concrete type declaration supported by the compilation unit
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public abstract class CompilationUnit<T extends TypeDeclaration> {
|
||||
|
||||
private final String packageName;
|
||||
|
||||
private final String name;
|
||||
|
||||
private final List<T> typeDeclarations = new ArrayList<>();
|
||||
|
||||
public CompilationUnit(String packageName, String name) {
|
||||
this.packageName = packageName;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getPackageName() {
|
||||
return this.packageName;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public T createTypeDeclaration(String name) {
|
||||
T typeDeclaration = doCreateTypeDeclaration(name);
|
||||
this.typeDeclarations.add(typeDeclaration);
|
||||
return typeDeclaration;
|
||||
}
|
||||
|
||||
public List<T> getTypeDeclarations() {
|
||||
return Collections.unmodifiableList(this.typeDeclarations);
|
||||
}
|
||||
|
||||
protected abstract T doCreateTypeDeclaration(String name);
|
||||
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* 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 io.spring.initializr.generator.language;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
|
||||
/**
|
||||
* A language in which a generated project can be written.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public interface Language {
|
||||
|
||||
/**
|
||||
* The default JVM version to use if none is specified.
|
||||
*/
|
||||
String DEFAULT_JVM_VERSION = "1.8";
|
||||
|
||||
String id();
|
||||
|
||||
String jvmVersion();
|
||||
|
||||
static Language forId(String id, String jvmVersion) {
|
||||
return SpringFactoriesLoader
|
||||
.loadFactories(LanguageFactory.class,
|
||||
LanguageFactory.class.getClassLoader())
|
||||
.stream().map((factory) -> factory.createLanguage(id, jvmVersion))
|
||||
.filter(Objects::nonNull).findFirst()
|
||||
.orElseThrow(() -> new IllegalStateException(
|
||||
"Unrecognized language id '" + id + "'"));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* 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 io.spring.initializr.generator.language;
|
||||
|
||||
/**
|
||||
* A factory for creating a {@link Language}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public interface LanguageFactory {
|
||||
|
||||
/**
|
||||
* Creates and returns a {@link Language} for the given id and JVM version. If the
|
||||
* factory does not recognise the given {@code id}, {@code null} should be returned.
|
||||
* @param id the id of the language
|
||||
* @param jvmVersion the jvm version or {@code null} to use the default
|
||||
* @return the language or {@code null}
|
||||
*/
|
||||
Language createLanguage(String id, String jvmVersion);
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* 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 io.spring.initializr.generator.language;
|
||||
|
||||
/**
|
||||
* A parameter, typically of a method or function.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class Parameter {
|
||||
|
||||
private final String type;
|
||||
|
||||
private final String name;
|
||||
|
||||
public Parameter(String type, String name) {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* 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 io.spring.initializr.generator.language;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* Representation of application source code.
|
||||
*
|
||||
* @param <T> types
|
||||
* @param <C> compilation units
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public abstract class SourceCode<T extends TypeDeclaration, C extends CompilationUnit<T>> {
|
||||
|
||||
private final List<C> compilationUnits = new ArrayList<>();
|
||||
|
||||
private final BiFunction<String, String, C> compilationUnitFactory;
|
||||
|
||||
protected SourceCode(BiFunction<String, String, C> compilationUnitFactory) {
|
||||
this.compilationUnitFactory = compilationUnitFactory;
|
||||
}
|
||||
|
||||
public C createCompilationUnit(String packageName, String name) {
|
||||
C compilationUnit = this.compilationUnitFactory.apply(packageName, name);
|
||||
this.compilationUnits.add(compilationUnit);
|
||||
return compilationUnit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an unmodifiable view of the {@link CompilationUnit compilation units}.
|
||||
* @return the compilation units
|
||||
*/
|
||||
public List<C> getCompilationUnits() {
|
||||
return Collections.unmodifiableList(this.compilationUnits);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* 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 io.spring.initializr.generator.language;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* A writer for some {@link SourceCode}.
|
||||
*
|
||||
* @param <S> the type of source code that can be written by this writer
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public interface SourceCodeWriter<S extends SourceCode<?, ?>> {
|
||||
|
||||
/**
|
||||
* Writes, to the given {@code directory}, the given {@code sourceCode}.
|
||||
* @param directory the root directory beneath which the source code is written
|
||||
* @param sourceCode the source code to write
|
||||
* @throws IOException if writing fails
|
||||
*/
|
||||
void writeTo(Path directory, S sourceCode) throws IOException;
|
||||
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* 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 io.spring.initializr.generator.language;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A type declared in a {@link CompilationUnit}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class TypeDeclaration implements Annotatable {
|
||||
|
||||
private final List<Annotation> annotations = new ArrayList<>();
|
||||
|
||||
private final String name;
|
||||
|
||||
private String extendedClassName;
|
||||
|
||||
public TypeDeclaration(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void extend(String name) {
|
||||
this.extendedClassName = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void annotate(Annotation annotation) {
|
||||
this.annotations.add(annotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Annotation> getAnnotations() {
|
||||
return Collections.unmodifiableList(this.annotations);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public String getExtends() {
|
||||
return this.extendedClassName;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Language abstraction.
|
||||
*/
|
||||
package io.spring.initializr.generator.language;
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* 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 io.spring.initializr.generator.language;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link Annotation}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class AnnotationTests {
|
||||
|
||||
@Test
|
||||
void annotationWithNoAttribute() {
|
||||
Annotation annotation = Annotation.name("com.example.Test");
|
||||
assertThat(annotation.getName()).isEqualTo("com.example.Test");
|
||||
assertThat(annotation.getAttributes()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void annotationWithSingleAttribute() {
|
||||
Annotation annotation = Annotation.name("com.example.Test",
|
||||
(builder) -> builder.attribute("test", Enum.class,
|
||||
"com.example.Unit.CENTURIES, com.example.Unit.NANOS"));
|
||||
assertThat(annotation.getName()).isEqualTo("com.example.Test");
|
||||
assertThat(annotation.getAttributes()).hasSize(1);
|
||||
Annotation.Attribute attribute = annotation.getAttributes().get(0);
|
||||
assertThat(attribute.getName()).isEqualTo("test");
|
||||
assertThat(attribute.getType()).isEqualTo(Enum.class);
|
||||
assertThat(attribute.getValues())
|
||||
.containsExactly("com.example.Unit.CENTURIES, com.example.Unit.NANOS");
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user