-
Notifications
You must be signed in to change notification settings - Fork 136
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
Support create java function project #51
Conversation
8478e55
to
1e5197e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't seem useful until we also support Java functions. Just want to make sure you have a plan to 'disable' this feature if Java function support isn't ready in time for our next release? Should be easy, right?
src/commands/createNewProject.ts
Outdated
switch (language.label) { | ||
case TemplateLanguage.Java: | ||
const groupIdPlaceHolder: string = localize('azFunc.java.groupIdPlaceholder', 'groupId'); | ||
const groupIdPrompt: string = localize('azFunc.java.groupIdPrompt', 'Provide value of "groupId"'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should be 'Provide a value for' instead of 'of'. In addition, there's no need to put 'groupId' in quotes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay
src/commands/createNewProject.ts
Outdated
const artifactIdprompt: string = localize('azFunc.java.artifactIdPrompt', 'Provide value of "artifactId"'); | ||
const artifactId: string = await ui.showInputBox(artifactIdPlaceHolder, artifactIdprompt, false); | ||
|
||
const versionPlaceHolder: string = localize('azFunc.java.versionPlaceHolder', '1.0-SNAPSHOT'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, the placeholder should match the prompt, not the default value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure
src/commands/createNewProject.ts
Outdated
const appNamePrompt: string = localize('azFunc.java.appNamePrompt', 'Provide value of "appName"'); | ||
const appName: string = await ui.showInputBox(appNamePlaceHolder, appNamePrompt, false, undefined, `${artifactId}-${Date.now()}`); | ||
|
||
// Use maven command currently, will change to function CLI when the function CLI init project command is ready. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually prefer this over using the function cli. All of the core logic is still encapsulated in the mvn archetypeArtifact, but now we get these benefits:
- A user can create a Java function project without the func cli installed.
- We don't have to wait for the func cli to be updated every time we want to change this
(Plus the func cli doesn't report exit codes correctly or display parse-able output - although both of those should be fixed)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently, the function CLI doesn't support create Java function project yet. Our plan is leverage the Maven archetype here first. And when the function CLI part is ready, we can change the implementation to using CLI. :)
BTW, according to the newest disscussion with CLI team, it is most likely that the java function project creation part in CLI will leveraging Maven plugin also. So I think we can change to CLI in the future. Anyway we can discuss wether to introduce CLI here in the future :)
src/commands/createNewProject.ts
Outdated
await fsUtil.writeFormattedJson(tasksJsonPath, TemplateFiles.tasksJson); | ||
await fsUtil.writeFormattedJson(launchJsonPath, TemplateFiles.launchJson); | ||
const vsCodePath: string = path.join(functionAppPath, '.vscode'); | ||
if (!await fse.pathExists(vsCodePath)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fse.ensureDir
does the same as these two commands
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
src/functions-cli.ts
Outdated
await new Promise((resolve: () => void, reject: (e: Error) => void): void => { | ||
const options: cp.SpawnOptions = { | ||
cwd: workingDirectory, | ||
shell: true | ||
}; | ||
const childProc: cp.ChildProcess = cp.spawn('func', args, options); | ||
const command: string = languageName === TemplateLanguage.Java ? 'mvn' : 'func'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
executeCommand
could be used for things other than creating a project. Let's pass in 'command' instead of 'languageName'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right.
src/commands/createNewProject.ts
Outdated
|
||
let javaTargetPath: string = ''; | ||
switch (language.label) { | ||
case TemplateLanguage.Java: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Can we move the Java-specific logic into a separate function? I would find it more readable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay.
src/template-files.ts
Outdated
presentation: { | ||
reveal: 'always' | ||
}, | ||
problemMatcher: [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A lot of this code is copied. Can we encapsulate it? At least the problemMatcher
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure.
src/template-files.ts
Outdated
taskName: 'Launch Function App', | ||
identifier: 'launchFunctionApp', | ||
linux: { | ||
command: 'sh -c "mvn clean package && func host start --script-root %path%"' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Create a separate 'cleanFunctionApp' task and use 'dependsOn' in this task. That way you don't have to define separate 'linux', 'osx', and 'windows' commands
Is 'mvn clean package' necessary before every F5? If so, this might not work since it's a background task (When the user detaches the debugger, func host start is still running in the background...it doesn not get executed again the next time the user F5's)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes mvn clean package
is necessary before every F5.
After trying locally, it's exactly as what you said. the preLaunchTask doesn't get executed again. I'm trying to figure out if there is any work around on this. Do you have any suggestions on this?
Currently the user can only hit ctrl+c to manually terminate the function host and hit F5 again.
src/template-files.ts
Outdated
return JSON.stringify(data, null, ' '); | ||
} | ||
|
||
export function getTasksJson(language: string, args: string): string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer if getTasksJson and getLaunchJson both returned the same type of string (formatted vs unformatted). Doing a stringifyJSON
and replace
seems inefficient, so I would lean towards returning unformatted strings. (Just modify the object directly - something like taskJsonForJava.tasks[0].command = "func host start --script-root" + scriptRoot
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just modify the object is good for me.
So shall we define the structure of the task json object here? Otherwise the object field cannot be accessed by .
. Or we use []
to access the field, but this may raise tslint error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the suggestion.
|
||
const folder: vscode.WorkspaceFolder | undefined = vscode.workspace.workspaceFolders.find((f: vscode.WorkspaceFolder): boolean => { | ||
return fsPath.startsWith(f.uri.fsPath); | ||
return path.relative(fsPath, f.uri.fsPath) === ''; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm - this definitely fixes some edge cases, but it's not quite what I originally intended the behavior to be. This function should return true even if the path is a subfolder of a workspace. Maybe something like this would work?:
const relativePath: string = path.relative(fsPath, f.uri.fsPath);
return relativePath === '' || !relativePath.startsWith('..');
This logic can be tricky with lots of edge cases, so I'd prefer to add some unit tests when we fix this. You can do that in this PR or file an issue to fix this separately (I don't mind fixing this myself)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My concern is if the subfolder is not opened, the user might not able to launch it since the cwd might not have .vscode
folder which contains launch.json
and task.json
.
Another concern is that as what we discussed above. The maven archetype will always create a artifactId folder first, and put function things into the folder. For Java, there is another important file: pom.xml
, will also be put into the artifactId folder. The maven command can be execute only if the cwd contains pom.xml
or specify its location in parameter. That's why we prefer to open the folder which contains pom.xml (that is the artifactId folder).
I quite agree that always open the project base path might not be the best solution for this. While I think dong this it not that harmful. What about keeping this change for now and file a issue and we can do more further discussion in detail?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah filing an issue is fine
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great
a7cbe1b
to
cc8d3b7
Compare
cc8d3b7
to
dcaa5ef
Compare
Close this PR since the code structure has changed largely. See #66 |
Work Item: #48
Support create java function project. Currently we will use Maven archetype (call mvn cli) to create a Java typed function project. And we'll change it to function cli when the related part in cli is ready.
UI:
Todo:
-------------- Update on Wed Nov 08 2017 09:59:31 GMT+0800 (China Standard Time) --------------
Add code to support add Java function.
Confirmed from Maven plugin team, this command has no batch mode, so I send it to terminal and user can fill in the parameter in the terminal
pom.xml
in the selected folder.