Skip to content

Commit 2e00cbd

Browse files
committed
Added update ref from project menu.
1 parent 1f478c6 commit 2e00cbd

File tree

14 files changed

+599
-382
lines changed

14 files changed

+599
-382
lines changed

src/ServiceStackIDEA/.idea/workspace.xml

Lines changed: 212 additions & 146 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/ServiceStackIDEA/META-INF/plugin.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
<extensions defaultExtensionNs="com.intellij">
2828
<!-- Add your extensions here -->
2929
<intentionAction>
30-
<className>UpdateServiceStackReference</className>
30+
<className>UpdateServiceStackReferenceIntention</className>
3131
<category>ServiceStack</category>
3232
<descriptionDirectoryName>ServiceStack</descriptionDirectoryName>
3333
</intentionAction>
@@ -47,5 +47,9 @@
4747
<add-to-group group-id="NewGroup" anchor="after" relative-to-action="NewAction"/>
4848
<keyboard-shortcut keymap="$default" first-keystroke="shift ctrl alt R"/>
4949
</action>
50+
<action id="UpdateServiceStackReference" class="UpdateServiceStackReference" text="Update ServiceStack Reference" icon="/icons/logo-16.png"
51+
description="Updates the selected ServiceStack reference.">
52+
<add-to-group group-id="ProjectViewPopupMenu"/>
53+
</action>
5054
</actions>
5155
</idea-plugin>

src/ServiceStackIDEA/out/production/ServiceStackIDEA/intentionDescriptions/UpdateServiceStackReference/description.html

Lines changed: 0 additions & 7 deletions
This file was deleted.

src/ServiceStackIDEA/out/production/ServiceStackIDEA/intentionDescriptions/UpdateServiceStackReference/after.java.template renamed to src/ServiceStackIDEA/out/production/ServiceStackIDEA/intentionDescriptions/UpdateServiceStackReferenceIntention/after.java.template

File renamed without changes.

src/ServiceStackIDEA/out/production/ServiceStackIDEA/intentionDescriptions/UpdateServiceStackReference/before.java.template renamed to src/ServiceStackIDEA/out/production/ServiceStackIDEA/intentionDescriptions/UpdateServiceStackReferenceIntention/before.java.template

File renamed without changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<html>
2+
<body>
3+
Update the current ServiceStack reference.
4+
<!-- tooltip end -->
5+
6+
</body>
7+
</html>

src/ServiceStackIDEA/src/AddServiceStackReference.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import com.intellij.facet.Facet;
22
import com.intellij.facet.FacetManager;
3-
import com.intellij.facet.FacetTypeId;
43
import com.intellij.openapi.actionSystem.AnAction;
54
import com.intellij.openapi.actionSystem.AnActionEvent;
65
import com.intellij.openapi.actionSystem.DataKeys;
Lines changed: 74 additions & 220 deletions
Original file line numberDiff line numberDiff line change
@@ -1,263 +1,117 @@
1-
import com.google.gson.Gson;
2-
import com.intellij.codeInsight.intention.impl.QuickEditAction;
3-
import com.intellij.notification.Notification;
4-
import com.intellij.notification.NotificationType;
5-
import com.intellij.notification.Notifications;
1+
import com.intellij.facet.Facet;
2+
import com.intellij.facet.FacetManager;
3+
import com.intellij.openapi.actionSystem.AnAction;
4+
import com.intellij.openapi.actionSystem.AnActionEvent;
5+
import com.intellij.openapi.actionSystem.DataKeys;
66
import com.intellij.openapi.application.ApplicationManager;
77
import com.intellij.openapi.command.CommandProcessor;
8-
import com.intellij.openapi.command.UndoConfirmationPolicy;
98
import com.intellij.openapi.editor.Document;
10-
import com.intellij.openapi.editor.Editor;
119
import com.intellij.openapi.fileEditor.FileDocumentManager;
10+
import com.intellij.openapi.module.Module;
11+
import com.intellij.openapi.module.ModuleManager;
1212
import com.intellij.openapi.project.Project;
13-
import com.intellij.openapi.util.Iconable;
14-
import com.intellij.openapi.util.TextRange;
15-
import com.intellij.openapi.vfs.ReadonlyStatusHandler;
1613
import com.intellij.openapi.vfs.VirtualFile;
17-
import com.intellij.psi.PsiClass;
14+
import com.intellij.psi.PsiDocumentManager;
1815
import com.intellij.psi.PsiFile;
19-
import com.intellij.psi.PsiFileFactory;
2016
import com.intellij.psi.PsiJavaFile;
21-
import com.intellij.psi.codeStyle.CodeStyleManager;
22-
import com.intellij.util.IncorrectOperationException;
23-
import org.apache.http.client.utils.URIBuilder;
2417
import org.jetbrains.annotations.NotNull;
18+
import org.jetbrains.annotations.Nullable;
2519

26-
import javax.swing.*;
27-
import java.io.BufferedReader;
28-
import java.io.IOException;
29-
import java.io.InputStreamReader;
30-
import java.net.MalformedURLException;
31-
import java.net.URISyntaxException;
32-
import java.net.URL;
33-
import java.net.URLConnection;
34-
import java.util.ArrayList;
35-
import java.util.List;
36-
import java.util.Scanner;
20+
import java.util.Objects;
3721

38-
39-
public class UpdateServiceStackReference extends QuickEditAction implements Iconable {
22+
/**
23+
* Created by Layoric on 9/04/2015.
24+
*/
25+
public class UpdateServiceStackReference extends AnAction {
4026

4127
@Override
42-
public String getText() {
43-
return "Update ServiceStack reference";
28+
public void actionPerformed(AnActionEvent anActionEvent) {
29+
final PsiJavaFile psiJavaFile = getPsiFile(anActionEvent);
30+
if(UpdateServiceStackUtils.containsOptionsHeader(psiJavaFile)) {
31+
ApplicationManager.getApplication().runWriteAction(new Runnable() {
32+
@Override
33+
public void run() {
34+
UpdateServiceStackUtils.updateServiceStackReference(psiJavaFile);
35+
}
36+
});
37+
}
4438
}
4539

4640
@Override
47-
public String getFamilyName() {
48-
return "UpdateServiceStackReference";
49-
}
41+
public void update(AnActionEvent e) {
42+
Module module = getModule(e);
43+
PsiJavaFile psiJavaFile = getPsiFile(e);
44+
if (psiJavaFile == null || !isAndroidProject(module)) {
45+
e.getPresentation().setVisible(false);
46+
return;
47+
}
5048

51-
@Override
52-
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile psiFile) {
53-
try {
54-
if(psiFile == null || !(psiFile instanceof PsiJavaFile)) {
55-
return false;
56-
}
57-
PsiJavaFile classFile = (PsiJavaFile)psiFile;
58-
if(containsOptionsHeader(classFile)) {
59-
return true;
60-
}
61-
} catch (Exception e) {
62-
e.printStackTrace();
49+
if(!UpdateServiceStackUtils.containsOptionsHeader(psiJavaFile)) {
50+
e.getPresentation().setVisible(false);
51+
return;
6352
}
64-
return false;
53+
e.getPresentation().setVisible(true);
54+
super.update(e);
6555
}
6656

67-
private boolean containsOptionsHeader(PsiJavaFile psiJavaFile) {
68-
Document dtoDocument = FileDocumentManager.getInstance().getDocument(psiJavaFile.getVirtualFile());
69-
if(dtoDocument == null) {
70-
return false;
57+
static Module getModule(Project project) {
58+
if (project == null)
59+
return null;
60+
Module[] modules = ModuleManager.getInstance(project).getModules();
61+
if (modules.length > 0) {
62+
return modules[0];
7163
}
72-
//Only pull in the first 1000 chars max to look for header.
73-
int range = dtoDocument.getTextLength() > 1000 ? 1000 : dtoDocument.getTextLength();
74-
String code = dtoDocument.getText(new TextRange(0,range));
64+
return null;
65+
}
7566

76-
String[] codeLines = code.split("\n");
77-
for(String line : codeLines) {
78-
if(line.startsWith("BaseUrl:")) {
67+
private static boolean isAndroidProject(@NotNull Module module) {
68+
Facet[] facetsByType = FacetManager.getInstance(module).getAllFacets();
69+
for (Facet facet :facetsByType) {
70+
if(Objects.equals(facet.getTypeId().toString(), "android")) {
7971
return true;
8072
}
8173
}
8274
return false;
8375
}
8476

85-
private boolean validateEndPoint(String url) {
77+
private static PsiJavaFile getPsiFile(AnActionEvent e) {
8678

87-
URL metadataUrl = null;
88-
URIBuilder builder = null;
89-
try {
90-
builder = new URIBuilder(url.replace("types/java","types/metadata"));
91-
builder.addParameter("format","json");
92-
metadataUrl = new URL(builder.build().toString());
93-
} catch (URISyntaxException e) {
94-
//Log error to IDEA warning bubble/window.
95-
e.printStackTrace();
96-
Notification notification = new Notification("ServiceStackIDEA", "Error Updating Reference", "Invalid BaseUrl provided", NotificationType.ERROR);
97-
Notifications.Bus.notify(notification);
98-
return false;
99-
} catch (MalformedURLException e) {
100-
e.printStackTrace();
101-
Notification notification = new Notification("ServiceStackIDEA", "Error Updating Reference", "Invalid BaseUrl provided", NotificationType.ERROR);
102-
Notifications.Bus.notify(notification);
103-
return false;
79+
Module module = getModule(e);
80+
if(module == null) {
81+
return null;
10482
}
105-
106-
URLConnection metadataConnection = null;
107-
String errorMessage = null;
108-
try {
109-
metadataConnection = metadataUrl.openConnection();
110-
} catch (IOException e) {
111-
errorMessage = "Problem connecting to BaseUrl - " + e.getMessage();
83+
VirtualFile selectedFile = DataKeys.VIRTUAL_FILE.getData(e.getDataContext());
84+
if(selectedFile == null) {
85+
return null;
11286
}
113-
metadataConnection.setRequestProperty("content-type", "application/json; charset=utf-8");
114-
BufferedReader metadataBufferReader = null;
115-
try {
116-
metadataBufferReader = new BufferedReader(
117-
new InputStreamReader(
118-
metadataConnection.getInputStream()));
119-
} catch (IOException e) {
120-
errorMessage = "Problem connecting to BaseUrl - " + e.getMessage();
87+
Document document = FileDocumentManager.getInstance().getDocument(selectedFile);
88+
if(document == null) {
89+
return null;
12190
}
122-
String metadataInputLine;
123-
StringBuilder metadataResponse = new StringBuilder();
124-
try {
125-
while ((metadataInputLine = metadataBufferReader.readLine()) != null)
126-
metadataResponse.append(metadataInputLine);
12791

128-
metadataBufferReader.close();
129-
} catch (IOException e) {
130-
errorMessage = "Invalid response, check the BaseUrl is a valid ServiceStack endpoint - " + e.getMessage();
92+
//Check if a 'PsiFile', display without a package name if no PsiFile.
93+
PsiFile psiFile = PsiDocumentManager.getInstance(module.getProject()).getPsiFile(document);
94+
if(psiFile == null) {
95+
return null;
13196
}
13297

133-
134-
String metadataJson = metadataResponse.toString();
135-
Gson gson = new Gson();
136-
try {
137-
ServiceStackMetadata metadata = gson.fromJson(metadataJson, ServiceStackMetadata.class);
138-
if (metadata == null || metadata.getConfig() == null || metadata.getConfig().getBaseUrl() == null) {
139-
errorMessage = "The address url is not a valid ServiceStack endpoint.";
140-
}
141-
} catch (Exception e) {
142-
errorMessage = "The address url is not a valid ServiceStack endpoint.";
143-
}
144-
145-
if(errorMessage != null) {
146-
Notification notification = new Notification("ServiceStackIDEA", "Error Updating Reference", errorMessage, NotificationType.ERROR);
147-
Notifications.Bus.notify(notification);
148-
return false;
98+
if(!isJavaFile(psiFile)) {
99+
return null;
149100
}
150-
151-
return true;
101+
return (PsiJavaFile)psiFile;
152102
}
153103

154-
@Override
155-
public void invoke(@NotNull Project project, Editor editor, final PsiFile psiFile) throws IncorrectOperationException {
156-
String code = psiFile.getText();
157-
Scanner scanner = new Scanner(code);
158-
List<String> linesOfCode = new ArrayList<>();
159-
while (scanner.hasNextLine()) {
160-
String line = scanner.nextLine();
161-
linesOfCode.add(line);
162-
if(line.startsWith("*/")) break;
163-
}
164-
scanner.close();
165-
166-
int startParamsIndex = 0;
167-
String baseUrl = null;
168-
for(String item : linesOfCode) {
169-
startParamsIndex++;
170-
if(item.startsWith("BaseUrl:")) {
171-
baseUrl = item.split(":",2)[1].trim();
172-
break;
173-
}
174-
}
175-
if(baseUrl == null) {
176-
Notification notification = new Notification("ServiceStackIDEA", "Error Updating Reference", "BaseUrl property not found.", NotificationType.ERROR);
177-
Notifications.Bus.notify(notification);
178-
return;
179-
}
180-
if(!baseUrl.endsWith("/")) {
181-
baseUrl += "/";
182-
}
183-
184-
URIBuilder builder = null;
185-
try {
186-
builder = new URIBuilder(baseUrl);
187-
} catch (URISyntaxException e) {
188-
//Log error to IDEA warning bubble/window.
189-
Notification notification = new Notification("ServiceStackIDEA", "Error Updating Reference", "Invalid BaseUrl provided", NotificationType.ERROR);
190-
Notifications.Bus.notify(notification);
191-
return;
192-
}
104+
private static boolean isJavaFile(@Nullable PsiFile psiFile) {
105+
return psiFile != null && psiFile instanceof PsiJavaFile;
106+
}
193107

194-
String existingPath = builder.getPath();
195-
if(existingPath == null || existingPath.equals("/")) {
196-
builder.setPath("/types/java");
108+
static Module getModule(AnActionEvent e) {
109+
Module module = e.getData(DataKeys.MODULE);
110+
if (module == null) {
111+
Project project = e.getData(DataKeys.PROJECT);
112+
return getModule(project);
197113
} else {
198-
builder.setPath(existingPath + "/types/java");
199-
}
200-
201-
202-
try {
203-
if(!validateEndPoint(builder.build().toString())) {
204-
return;
205-
}
206-
} catch (URISyntaxException e) {
207-
e.printStackTrace();
208-
Notification notification = new Notification("ServiceStackIDEA", "Error Updating Reference", "Unable to parse BaseUrl", NotificationType.ERROR);
209-
Notifications.Bus.notify(notification);
210-
return;
211-
}
212-
213-
for(int i = startParamsIndex; i < linesOfCode.size(); i++) {
214-
String configLine = linesOfCode.get(i);
215-
if(!configLine.startsWith("//") && configLine.contains(":")) {
216-
String[] keyVal = configLine.split(":");
217-
builder.addParameter(keyVal[0],keyVal[1].trim());
218-
}
114+
return module;
219115
}
220-
221-
try {
222-
String serverUrl = builder.build().toString();
223-
URL javaCodeUrl = new URL(serverUrl);
224-
225-
URLConnection javaCodeConnection = javaCodeUrl.openConnection();
226-
javaCodeConnection.setRequestProperty("content-type", "application/json; charset=utf-8");
227-
BufferedReader javaCodeBufferReader = new BufferedReader(
228-
new InputStreamReader(
229-
javaCodeConnection.getInputStream()));
230-
String javaCodeInput;
231-
StringBuilder javaCodeResponse = new StringBuilder();
232-
while ((javaCodeInput = javaCodeBufferReader.readLine()) != null) {
233-
javaCodeResponse.append(javaCodeInput);
234-
//All documents inside IntelliJ IDEA always use \n line separators.
235-
//http://confluence.jetbrains.net/display/IDEADEV/IntelliJ+IDEA+Architectural+Overview
236-
javaCodeResponse.append("\n");
237-
}
238-
239-
Document document = FileDocumentManager.getInstance().getDocument(psiFile.getVirtualFile());
240-
if (document != null) {
241-
document.setText(javaCodeResponse);
242-
} else {
243-
//Show error
244-
Notification notification = new Notification("ServiceStackIDEA", "Error Updating Reference", "DTO file not found.", NotificationType.ERROR);
245-
Notifications.Bus.notify(notification);
246-
}
247-
} catch (Exception e) {
248-
Notification notification = new Notification("ServiceStackIDEA", "Error Updating Reference", "Invalid BaseUrl provided", NotificationType.ERROR);
249-
Notifications.Bus.notify(notification);
250-
e.printStackTrace();
251-
}
252-
}
253-
254-
@Override
255-
public boolean startInWriteAction() {
256-
return true;
257-
}
258-
259-
@Override
260-
public Icon getIcon(@IconFlags int i) {
261-
return new ImageIcon(this.getClass().getResource("/icons/logo-16.png"));
262116
}
263117
}

0 commit comments

Comments
 (0)