Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more suitable default template for LF projects to Epoch #1180

Merged
merged 6 commits into from
May 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 102 additions & 64 deletions org.lflang.ui/src/org/lflang/ui/wizard/LFProjectTemplateProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,30 @@
import org.eclipse.xtext.ui.wizard.template.StringSelectionTemplateVariable;

/**
* Create a list with all project templates to be shown in the template new project wizard.
* Create a list with all project templates to be shown in the template new
* project wizard. Each template is able to generate one or more projects. Each
* project can be configured such that any number of files are included.
*
* Each template is able to generate one or more projects. Each project can be configured such that any number of files are included.
* NOTE:
* Xtext is responsible for automatically populating the contents of several
* files in this package based on the parameters given to the @ProjectTemplate
* annotations. However, this mechanism appears to be broken.
* Upon adding a new template, manually add entries to messages.properties and
* Messages.java in order to get the template registered properly in the wizard.
*/
@SuppressWarnings("restriction")
class LFProjectTemplateProvider implements IProjectTemplateProvider {
@Override
public AbstractProjectTemplate[] getProjectTemplates() {
return new AbstractProjectTemplate[] { new FederatedProject(),
new HelloWorldProject(), new InteractiveProject(),
new ParallelProject(), new PipelineProject(),
new ReflexGameProject(), new WebServerProject()};
}
@Override
public AbstractProjectTemplate[] getProjectTemplates() {
return new AbstractProjectTemplate[] { new DefaultProject(),
new FederatedProject(), new HelloWorldProject(),
new InteractiveProject(), new ParallelProject(),
new PipelineProject(), new ReflexGameProject(),
new WebServerProject() };
}
}

@SuppressWarnings("restriction")
abstract class LFProjectTemplate extends AbstractProjectTemplate {

ProjectFactory setup(List<String> folders) {
var proj = new PluginProjectFactory();
proj.setProjectName(this.getProjectInfo().getProjectName());
Expand All @@ -43,54 +49,76 @@ ProjectFactory setup(List<String> folders) {
proj.addFolders(folders);
return proj;
}

String readFromFile(String target, String fileName) {
var stream = this.getClass().getResourceAsStream("templates/" + target + "/" + fileName);
var stream = this.getClass()
.getResourceAsStream("templates/" + target + "/" + fileName);
var str = "";
if (stream != null) {
str = new BufferedReader(
new InputStreamReader(stream)
).lines().collect(Collectors.joining("\n"));
str = new BufferedReader(new InputStreamReader(stream)).lines()
.collect(Collectors.joining("\n"));
} else {
throw new RuntimeException("Unable to open template for '" + fileName + "'");
throw new RuntimeException(
"Unable to open template for '" + fileName + "'");
}
return str;
}
}

@SuppressWarnings("restriction")
@ProjectTemplate(label="Parallel", icon="project_template.png", description="<p><b>Parallel</b></p><p>A simple" +
" fork-join pattern that exploits parallelism.</p>")
@ProjectTemplate(
label = "Default",
icon = "project_template.png",
description = "<p><b>Default</b></p><p>Project with an empty main reactor.</p>")
final class DefaultProject extends LFProjectTemplate {

@Override
public void generateProjects(IProjectGenerator generator) {
var proj = setup(List.of("src"));
var fileName = "src/Main.lf";
this.addFile(proj, fileName, readFromFile("c", fileName));
generator.generate(proj);
}
}

@ProjectTemplate(
label = "Pipeline",
icon = "project_template.png",
description = "<p><b>Parallel</b></p><p>A simple" +
" pipeline pattern that exploits parallelism.</p>")
final class PipelineProject extends LFProjectTemplate {

@Override
public void generateProjects(IProjectGenerator generator) {
@Override
public void generateProjects(IProjectGenerator generator) {
var proj = setup(List.of("src"));
var fileName = "src/Pipeline.lf";
this.addFile(proj, fileName, readFromFile("c", fileName));
generator.generate(proj);
}
}

@ProjectTemplate(label="Federated", icon="project_template.png", description="<p><b>Federated</b></p>" +
"<p>A federated \"Hello World\" program.</p>")
@SuppressWarnings("restriction")
@ProjectTemplate(
label = "Federated",
icon = "project_template.png",
description = "<p><b>Federated</b></p>" +
"<p>A federated \"Hello World\" program.</p>")
final class FederatedProject extends LFProjectTemplate {

@Override
public void generateProjects(IProjectGenerator generator) {
var proj = setup(List.of("src"));
var fileName = "src/FederatedHelloWorld.lf";
this.addFile(proj, fileName, readFromFile("c", fileName));
generator.generate(proj);
generator.generate(proj);
}
}

@ProjectTemplate(label="Parallel", icon="project_template.png", description="<p><b>Parallel</b></p>" +
"<p>A simple fork-join pattern that exploits parallelism.</p>")
@SuppressWarnings("restriction")
@ProjectTemplate(
label = "Parallel",
icon = "project_template.png",
description = "<p><b>Parallel</b></p>" +
"<p>A simple fork-join pattern that exploits parallelism.</p>")
final class ParallelProject extends LFProjectTemplate {

@Override
public void generateProjects(IProjectGenerator generator) {
var proj = setup(List.of("src"));
Expand All @@ -100,75 +128,85 @@ public void generateProjects(IProjectGenerator generator) {
}
}

@ProjectTemplate(label="Hello World", icon="project_template.png", description="<p><b>Hello World</b></p>" +
"<p>Print \"Hello world!\" in a target language of choice.</p>")
@SuppressWarnings("restriction")
@ProjectTemplate(
label = "Hello World",
icon = "project_template.png",
description = "<p><b>Hello World</b></p>" +
"<p>Print \"Hello world!\" in a target language of choice.</p>")
final class HelloWorldProject extends LFProjectTemplate {
GroupTemplateVariable config = group("Configuration");
// FIXME: draw from Target enum instead
StringSelectionTemplateVariable target = combo("Target:", new String[] {"C", "C++", "Python", "TypeScript"}, "The target language to compile down to", config);

StringSelectionTemplateVariable target = combo("Target:",
new String[] { "C", "C++", "Python", "TypeScript" },
"The target language to compile down to", config);

@Override
public void generateProjects(IProjectGenerator generator) {
var proj = setup(List.of("src"));
var fileName = "src/HelloWorld.lf";
switch (target.getValue()) {
case "C++":
addFile(proj, fileName, readFromFile("cpp", fileName));
break;
case "C":
addFile(proj, fileName, readFromFile("c", fileName));
break;
case "Python":
addFile(proj, fileName, readFromFile("py", fileName));
break;
case "TypeScript":
addFile(proj, fileName, readFromFile("ts", fileName));
break;
case "C++":
addFile(proj, fileName, readFromFile("cpp", fileName));
break;
case "C":
addFile(proj, fileName, readFromFile("c", fileName));
break;
case "Python":
addFile(proj, fileName, readFromFile("py", fileName));
break;
case "TypeScript":
addFile(proj, fileName, readFromFile("ts", fileName));
break;
}
generator.generate(proj);
}
}

@ProjectTemplate(label="Interactive", icon="project_template.png", description="<p><b>Interactive</b></p>" +
"<p>Simulate sensor input through key strokes.</p>")
@SuppressWarnings("restriction")
@ProjectTemplate(
label = "Interactive",
icon = "project_template.png",
description = "<p><b>Interactive</b></p>" +
"<p>Simulate sensor input through key strokes.</p>")
final class InteractiveProject extends LFProjectTemplate {

@Override
public void generateProjects(IProjectGenerator generator) {
var proj = setup(List.of("src", "src/include"));
var fileName = "src/Interactive.lf";
var fileName = "src/Interactive.lf";
this.addFile(proj, fileName, readFromFile("c", fileName));
var cmakeFile = "src/include/ncurses-cmake-extension.txt";
this.addFile(proj, cmakeFile, readFromFile("c", cmakeFile));
generator.generate(proj);
}
}

@ProjectTemplate(label="WebServer", icon="project_template.png", description="<p><b>Web Server</b></p>" +
"<p>A simple web server implemented using TypeScript.</p>")
@SuppressWarnings("restriction")
@ProjectTemplate(
label = "WebServer",
icon = "project_template.png",
description = "<p><b>Web Server</b></p>" +
"<p>A simple web server implemented using TypeScript.</p>")
final class WebServerProject extends LFProjectTemplate {

@Override
public void generateProjects(IProjectGenerator generator) {
var proj = setup(List.of("src"));
var fileName = "src/WebServer.lf";
var fileName = "src/WebServer.lf";
this.addFile(proj, fileName, readFromFile("ts", fileName));
generator.generate(proj);
}
}

@ProjectTemplate(label="ReflexGame", icon="project_template.png", description="<p><b>ReflexGame</b></p>" +
"<p>A simple reflex game.</p>")
@SuppressWarnings("restriction")
@ProjectTemplate(
label = "ReflexGame",
icon = "project_template.png",
description = "<p><b>ReflexGame</b></p>" +
"<p>A simple reflex game.</p>")
final class ReflexGameProject extends LFProjectTemplate {
GroupTemplateVariable config = group("Configuration");
// FIXME: draw from Target enum instead
StringSelectionTemplateVariable target = combo("Target:",
new String[] { "C" },
"The target language to compile down to", config);
new String[] { "C" }, "The target language to compile down to",
config);

@Override
public void generateProjects(IProjectGenerator generator) {
Expand Down
6 changes: 3 additions & 3 deletions org.lflang.ui/src/org/lflang/ui/wizard/Messages.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@

public class Messages extends NLS {
private static final String BUNDLE_NAME = "org.lflang.ui.wizard.messages"; //$NON-NLS-1$


public static String DefaultProject_Label;
public static String DefaultProject_Description;
public static String HelloWorldProject_Label;
public static String HelloWorldProject_Description;
public static String InteractiveProject_Label;
public static String InteractiveProject_Description;
public static String WebserverProject_Label;
public static String WebserverProject_Description;
public static String WebServerProject_Label;
public static String WebServerProject_Description;
public static String ReflexGameProject_Label;
Expand Down
4 changes: 2 additions & 2 deletions org.lflang.ui/src/org/lflang/ui/wizard/messages.properties
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
DefaultProject_Label=Default
DefaultProject_Description=<p><b>Default</b></p><p>Project with an empty main reactor.</p>
HelloWorldProject_Label=Hello World
HelloWorldProject_Description=<p><b>Hello World</b></p> <p>Print "Hello world!" in a target language of choice.</p>
InteractiveProject_Label=Interactive
InteractiveProject_Description=<p><b>Interactive</b></p> <p>Simulate sensor input through key strokes.</p>
WebserverProject_Label=WebServer
WebserverProject_Description=<p><b>Web Server</b></p> <p>A simple web server implemented using TypeScript.</p>
WebServerProject_Label=WebServer
WebServerProject_Description=<p><b>Web Server</b></p> <p>A simple web server implemented using TypeScript.</p>
ReflexGameProject_Label=ReflexGame
Expand Down
10 changes: 10 additions & 0 deletions org.lflang.ui/src/org/lflang/ui/wizard/templates/c/src/Main.lf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
target C // Other options: Python, Cpp, TypeScript, Rust.

// Import and/or declare reactor classes.

main reactor {

// Instantiate reactors.

// Connect ports.
}