From 29de49f105c23caf0e21bfec1b27cf47b0a6cdba Mon Sep 17 00:00:00 2001 From: Darren Reid Date: Wed, 18 Oct 2023 16:38:06 +1100 Subject: [PATCH] Add support for PHPStorm and NativeTypesLanguage.Php. --- CHANGELOG.md | 2 + build.gradle.kts | 1 + gradle.properties | 4 +- .../servicestack/idea/AddPythonAction.java | 3 - .../net/servicestack/idea/AddPythonRef.java | 4 +- .../idea/GradleBuildFileHelper.java | 23 +- .../servicestack/idea/IDEAPomFileHelper.java | 16 +- .../servicestack/idea/NativeTypeUtils.java | 2 + .../servicestack/idea/common/IDEAUtils.java | 8 +- .../idea/common/NativeTypesLanguage.java | 1 + .../servicestack/idea/php/AddPhpAction.java | 103 +++++++++ .../net/servicestack/idea/php/AddPhpRef.form | 160 ++++++++++++++ .../net/servicestack/idea/php/AddPhpRef.java | 205 ++++++++++++++++++ .../idea/php/AddPhpRefHandler.java | 143 ++++++++++++ .../idea/php/PhpNativeTypesHandler.java | 36 +++ src/main/resources/META-INF/phpstorm.xml | 10 + src/main/resources/META-INF/plugin.xml | 1 + 17 files changed, 701 insertions(+), 21 deletions(-) create mode 100644 src/main/java/net/servicestack/idea/php/AddPhpAction.java create mode 100644 src/main/java/net/servicestack/idea/php/AddPhpRef.form create mode 100644 src/main/java/net/servicestack/idea/php/AddPhpRef.java create mode 100644 src/main/java/net/servicestack/idea/php/AddPhpRefHandler.java create mode 100644 src/main/java/net/servicestack/idea/php/PhpNativeTypesHandler.java create mode 100644 src/main/resources/META-INF/phpstorm.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index f7e6bcc..e82ba25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ # ServiceStackIDEA Changelog ## [Unreleased] +- Add support for PHPStorm and Add ServiceStack Reference +- Resolve some issues with IntelliJ context menus ## [1.3.4] - Fix issue for Kotlin setups using `build.gradle.kts` files. ## [1.3.3] diff --git a/build.gradle.kts b/build.gradle.kts index ea811a6..da681cb 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -126,6 +126,7 @@ tasks { from("src/main/resources/META-INF") { include("intellij.xml") include("pycharm.xml") + include("phpstorm.xml") } } } diff --git a/gradle.properties b/gradle.properties index f8ff787..60496fd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ pluginGroup = ServiceStackIDEA pluginName = ServiceStack -pluginVersion = 1.3.4 +pluginVersion = 1.4.0 # See https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html # for insight into build numbers and IntelliJ Platform versions. @@ -20,7 +20,7 @@ platformDownloadSources = true # Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html # Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22 -platformPlugins = maven, java, PythonCore:211.6693.119 +platformPlugins = maven, java, PythonCore:211.6693.119,com.jetbrains.php:211.6693.120 # Opt-out flag for bundling Kotlin standard library. # See https://plugins.jetbrains.com/docs/intellij/kotlin.html#kotlin-standard-library for details. diff --git a/src/main/java/net/servicestack/idea/AddPythonAction.java b/src/main/java/net/servicestack/idea/AddPythonAction.java index 7cbbc0b..4e15cd9 100644 --- a/src/main/java/net/servicestack/idea/AddPythonAction.java +++ b/src/main/java/net/servicestack/idea/AddPythonAction.java @@ -8,12 +8,9 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; import com.jetbrains.python.PythonFileType; -import com.jetbrains.python.facet.PythonFacet; -import com.jetbrains.python.facet.PythonFacetSettings; import net.servicestack.idea.common.INativeTypesHandler; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/net/servicestack/idea/AddPythonRef.java b/src/main/java/net/servicestack/idea/AddPythonRef.java index 2b0f7af..5bb35b1 100644 --- a/src/main/java/net/servicestack/idea/AddPythonRef.java +++ b/src/main/java/net/servicestack/idea/AddPythonRef.java @@ -55,7 +55,7 @@ public boolean verify(JComponent input) { text = ((JTextField) input).getText(); } - return text != null && text.length() > 0; + return text != null && !text.isEmpty(); } @Override @@ -78,7 +78,7 @@ public boolean verify(JComponent input) { text = ((JTextField) input).getText(); } - return text != null && text.length() > 0; + return text != null && !text.isEmpty(); } @Override diff --git a/src/main/java/net/servicestack/idea/GradleBuildFileHelper.java b/src/main/java/net/servicestack/idea/GradleBuildFileHelper.java index d729b97..694af5f 100644 --- a/src/main/java/net/servicestack/idea/GradleBuildFileHelper.java +++ b/src/main/java/net/servicestack/idea/GradleBuildFileHelper.java @@ -130,37 +130,46 @@ public static Boolean isUsingKotlin(AnActionEvent event){ public static File getGradleBuildFile(AnActionEvent event) { VirtualFile vFile = event.getData(CommonDataKeys.VIRTUAL_FILE); Project project = event.getData(CommonDataKeys.PROJECT); - assert project != null; + + if (project == null || vFile == null) { + return null; + } + String projectBase = project.getBasePath(); - assert projectBase != null; + if (projectBase == null) { + return null; + } + File projectBaseFile = new File(projectBase); projectBase = projectBaseFile.getAbsolutePath(); - assert vFile != null; String basePath = vFile.isDirectory() ? vFile.getPath() : vFile.getParent().getPath(); File file = new File(basePath); File gradleFile = null; int count = 0; int maxDepth = 8; - while(true) { + + while (true) { File[] matchingFiles = file.listFiles((dir, name) -> name.startsWith("build.gradle")); boolean foundFile = matchingFiles != null && matchingFiles.length != 0; - if(foundFile) { + if (foundFile) { gradleFile = matchingFiles[0]; break; } + // project base even on Windows value is "c:/x/" using the wrong file separator. - if(file.getAbsolutePath().equals(projectBase) || count >= maxDepth) { + if (file.getAbsolutePath().equals(projectBase) || count >= maxDepth) { break; } + count++; file = file.getParentFile(); } return gradleFile; - } + public static File getDartPubspec(Module module) { String projDir = module.getProject().getBasePath(); if (projDir == null) { diff --git a/src/main/java/net/servicestack/idea/IDEAPomFileHelper.java b/src/main/java/net/servicestack/idea/IDEAPomFileHelper.java index 898e468..128a61f 100644 --- a/src/main/java/net/servicestack/idea/IDEAPomFileHelper.java +++ b/src/main/java/net/servicestack/idea/IDEAPomFileHelper.java @@ -88,7 +88,9 @@ private void PomAppendDependency(final Module module, final File pomFile, String newDepNode.appendChild(groupNode); newDepNode.appendChild(artifactNode); newDepNode.appendChild(versionNode); - assert dependenciesNode != null; + if(dependenciesNode == null) { + return; + } dependenciesNode.appendChild(newDepNode); TransformerFactory transformerFactory = TransformerFactory.newInstance(); @@ -101,10 +103,14 @@ private void PomAppendDependency(final Module module, final File pomFile, String final Project project = module.getProject(); final VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByIoFile(pomFile); - assert virtualFile != null; + if(virtualFile == null) { + return; + } final com.intellij.openapi.editor.Document document = FileDocumentManager.getInstance().getDocument(virtualFile); final FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance(); - assert document != null; + if(document == null) { + return; + } fileDocumentManager.saveDocument(document); //when file is edited and editor is closed, it is needed to save the text PsiDocumentManager.getInstance(project).commitDocument(document); PsiDocumentManager.getInstance(module.getProject()).commitAllDocuments(); @@ -148,7 +154,9 @@ public static boolean pomHasMavenDependency(File pomFile, String groupId, String } Node dependencies = getMavenDependenciesNode(doc); - assert dependencies != null; + if(dependencies == null) { + return false; + } NodeList depElements = dependencies.getChildNodes(); for (int i = 0; i < depElements.getLength(); i++) { Node dependencyElement = depElements.item(i); diff --git a/src/main/java/net/servicestack/idea/NativeTypeUtils.java b/src/main/java/net/servicestack/idea/NativeTypeUtils.java index 84eb87e..709bd92 100644 --- a/src/main/java/net/servicestack/idea/NativeTypeUtils.java +++ b/src/main/java/net/servicestack/idea/NativeTypeUtils.java @@ -4,6 +4,7 @@ import net.servicestack.idea.common.MjsNativeTypesHandler; import net.servicestack.idea.common.TypeScriptConcreteNativeTypesHandler; import net.servicestack.idea.common.TypeScriptNativeTypesHandler; +import net.servicestack.idea.php.PhpNativeTypesHandler; public class NativeTypeUtils { @@ -11,6 +12,7 @@ public static INativeTypesHandler getNativeTypesHandler(String fileName) { INativeTypesHandler result = null; if (fileName.endsWith(".kt")) result = new KotlinNativeTypesHandler(); if (fileName.endsWith(".java")) result = new JavaNativeTypesHandler(); + if (fileName.endsWith(".php")) result = new PhpNativeTypesHandler(); if (fileName.endsWith("dtos.dart")) result = new DartNativeTypesHandler(); if (fileName.endsWith("dtos.ts")) result = new TypeScriptConcreteNativeTypesHandler(); if (fileName.endsWith("dtos.d.ts")) result = new TypeScriptNativeTypesHandler(); diff --git a/src/main/java/net/servicestack/idea/common/IDEAUtils.java b/src/main/java/net/servicestack/idea/common/IDEAUtils.java index 7934d3e..6593154 100644 --- a/src/main/java/net/servicestack/idea/common/IDEAUtils.java +++ b/src/main/java/net/servicestack/idea/common/IDEAUtils.java @@ -14,6 +14,8 @@ import java.io.*; import java.net.URL; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.List; import java.util.Objects; @@ -63,7 +65,7 @@ public static boolean writeDtoFile(List codeLines, String path, StringBu BufferedWriter writer = null; boolean result = true; try { - writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path), StandardCharsets.UTF_8)); + writer = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get(path)), StandardCharsets.UTF_8)); for (String item : codeLines) { writer.write(item); writer.newLine(); @@ -73,8 +75,8 @@ public static boolean writeDtoFile(List codeLines, String path, StringBu errorMessage.append("Error writing DTOs to file - ").append(ex.getMessage()); } finally { try { - assert writer != null; - writer.close(); + if(writer != null) + writer.close(); } catch (Exception ignored) { } } diff --git a/src/main/java/net/servicestack/idea/common/NativeTypesLanguage.java b/src/main/java/net/servicestack/idea/common/NativeTypesLanguage.java index 5a66c97..292ccd2 100644 --- a/src/main/java/net/servicestack/idea/common/NativeTypesLanguage.java +++ b/src/main/java/net/servicestack/idea/common/NativeTypesLanguage.java @@ -10,6 +10,7 @@ public enum NativeTypesLanguage { Java, Kotlin, Mjs, + Php, Python, TypeScript, TypeScriptConcrete, diff --git a/src/main/java/net/servicestack/idea/php/AddPhpAction.java b/src/main/java/net/servicestack/idea/php/AddPhpAction.java new file mode 100644 index 0000000..6b4a76e --- /dev/null +++ b/src/main/java/net/servicestack/idea/php/AddPhpAction.java @@ -0,0 +1,103 @@ +package net.servicestack.idea.php; + +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.LangDataKeys; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiElement; +import com.jetbrains.php.lang.PhpFileType; +import org.jetbrains.annotations.NotNull; + +public class AddPhpAction extends AnAction { + @Override + public void actionPerformed(@NotNull AnActionEvent anActionEvent) { + Module module = getModule(anActionEvent); + AddPhpRef dialog = new AddPhpRef(module); // Create your AddPhpRef dialog similar to your existing AddPythonRef + dialog.pack(); + dialog.setLocationRelativeTo(null); + dialog.setSize(dialog.getPreferredSize()); + dialog.setResizable(true); + dialog.setTitle("Add PHP ServiceStack Reference"); + PsiElement element = LangDataKeys.PSI_ELEMENT.getData(anActionEvent.getDataContext()); + if (element instanceof PsiDirectory) { + PsiDirectory selectedDir = (PsiDirectory)element; + dialog.setSelectedDirectory(selectedDir.getVirtualFile().getPath()); + dialog.setFileName("dtos"); + } + showDialog(dialog); + } + + private void showDialog(AddPhpRef dialog) { + dialog.setVisible(true); + } + + @Override + public void update(@NotNull AnActionEvent e) { + Module module = getModule(e); + if (module == null) { + e.getPresentation().setEnabled(false); + } + + if (!isPhpModule(module)) { // Checking if this is a PHP project + e.getPresentation().setVisible(false); + } + + super.update(e); + } + + public boolean isPhpModule(Module module) { + if (module == null) { + return false; + } + + // Retrieve the module's root manager + ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module); + + // Retrieve the module's content roots + VirtualFile[] roots = moduleRootManager.getContentRoots(); + + // Iterate over each root file + for (VirtualFile rootFile : roots) { + VirtualFile[] children = rootFile.getChildren(); + + // Iterate over each child file + for (VirtualFile childFile : children) { + // Check if a child file is 'composer.json' or 'index.php' + String fileName = childFile.getName(); + if ("composer.json".equals(fileName) || "index.php".equals(fileName)) { + return true; + } + } + } + + // If neither 'composer.json' nor 'index.php' are found, return false + return false; + } + + + static Module getModule(Project project) { + if (project == null) + return null; + Module[] modules = ModuleManager.getInstance(project).getModules(); + if (modules.length > 0) { + return modules[0]; + } + return null; + } + + static Module getModule(AnActionEvent e) { + Module module = e.getData(LangDataKeys.MODULE); + if (module == null) { + Project project = e.getData(LangDataKeys.PROJECT); + return getModule(project); + } else { + return module; + } + } +} + diff --git a/src/main/java/net/servicestack/idea/php/AddPhpRef.form b/src/main/java/net/servicestack/idea/php/AddPhpRef.form new file mode 100644 index 0000000..5e3b617 --- /dev/null +++ b/src/main/java/net/servicestack/idea/php/AddPhpRef.form @@ -0,0 +1,160 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/net/servicestack/idea/php/AddPhpRef.java b/src/main/java/net/servicestack/idea/php/AddPhpRef.java new file mode 100644 index 0000000..fff19a6 --- /dev/null +++ b/src/main/java/net/servicestack/idea/php/AddPhpRef.java @@ -0,0 +1,205 @@ +package net.servicestack.idea.php; + +import com.intellij.openapi.module.Module; +import com.intellij.ui.JBColor; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.net.URL; + +public class AddPhpRef extends JDialog { + private JPanel contentPane; + private JButton buttonOK; + private JButton buttonCancel; + private JTextField addressUrlTextField; + private JTextField nameTextField; + private JTextPane infoTextPane; + private JTextPane errorTextPane; + + private String selectedDirectory; + private String errorMessage; + + private final Module module; + + public void setSelectedDirectory(String selectedDirectory) { + this.selectedDirectory = selectedDirectory; + } + + public void setFileName(String fileName) { + this.nameTextField.setText(fileName); + } + + public AddPhpRef(Module module) { + this.module = module; + setContentPane(contentPane); + setModal(true); + getRootPane().setDefaultButton(buttonOK); + ImageIcon imageIcon = createImageIcon(); + if (imageIcon != null) { + this.setIconImage(imageIcon.getImage()); + } + errorTextPane.setForeground(JBColor.RED); + + buttonOK.setEnabled(false); + + addressUrlTextField.setInputVerifier(new InputVerifier() { + @Override + public boolean verify(JComponent input) { + String text = null; + if (input instanceof JTextField) { + text = ((JTextField) input).getText(); + } + + return text != null && !text.isEmpty(); + } + + @Override + public boolean shouldYieldFocus(JComponent input) { + boolean valid = verify(input); + if (!valid) { + errorMessage = "URL Address is required"; + errorTextPane.setVisible(true); + errorTextPane.setText(errorMessage); + } + + return true; + } + }); + nameTextField.setInputVerifier(new InputVerifier() { + @Override + public boolean verify(JComponent input) { + String text = null; + if (input instanceof JTextField) { + text = ((JTextField) input).getText(); + } + + return text != null && !text.isEmpty(); + } + + @Override + public boolean shouldYieldFocus(JComponent input) { + boolean valid = verify(input); + if (!valid) { + errorMessage = "A file name is required."; + errorTextPane.setVisible(true); + errorTextPane.setText(errorMessage); + } + + return true; + } + }); + + nameTextField.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void insertUpdate(DocumentEvent e) { + warn(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + warn(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + warn(); + } + + public void warn() { + buttonOK.setEnabled(nameTextField.getInputVerifier().verify(nameTextField) && addressUrlTextField.getInputVerifier().verify(addressUrlTextField)); + } + }); + + addressUrlTextField.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void insertUpdate(DocumentEvent e) { + warn(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + warn(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + warn(); + } + + public void warn() { + buttonOK.setEnabled(nameTextField.getInputVerifier().verify(nameTextField) && addressUrlTextField.getInputVerifier().verify(addressUrlTextField)); + } + }); + + buttonOK.addActionListener(e -> onOK()); + + buttonCancel.addActionListener(e -> onCancel()); + +// call onCancel() when cross is clicked + setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + onCancel(); + } + }); + +// call onCancel() on ESCAPE + contentPane.registerKeyboardAction(e -> onCancel(), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + } + + private void onOK() { + buttonOK.setEnabled(false); + StringBuilder errorMessageBuilder = new StringBuilder(); + try { + AddPhpRefHandler.handleOk( + this.module, + this.addressUrlTextField.getText(), + this.nameTextField.getText(), + this.selectedDirectory, + errorMessageBuilder + ); + if (!errorMessageBuilder.toString().isEmpty()) { + errorTextPane.setText(errorMessageBuilder.toString()); + errorTextPane.setVisible(true); + } else { + dispose(); + } + } catch (Exception e) { + errorMessageBuilder.append("An unexpected error has occurred. - "); + errorMessageBuilder.append(e.getMessage()); + e.printStackTrace(); + } finally { + if (!errorMessageBuilder.toString().isEmpty()) { + errorTextPane.setText(errorMessageBuilder.toString()); + errorTextPane.setVisible(true); + buttonOK.setEnabled(true); + } + } + } + + private void onCancel() { + // add your code here if necessary + dispose(); + } + + public static void main(String[] args) { + AddPhpRef dialog = new AddPhpRef(null); + dialog.pack(); + dialog.setVisible(true); + System.exit(0); + } + + private ImageIcon createImageIcon() { + URL imgURL = getClass().getResource("/logo-16.png"); + if (imgURL != null) { + return new ImageIcon(imgURL, "ServiceStack"); + } else { + System.err.println("Couldn't find file: " + "/logo-16.png"); + return null; + } + } +} diff --git a/src/main/java/net/servicestack/idea/php/AddPhpRefHandler.java b/src/main/java/net/servicestack/idea/php/AddPhpRefHandler.java new file mode 100644 index 0000000..c8340fe --- /dev/null +++ b/src/main/java/net/servicestack/idea/php/AddPhpRefHandler.java @@ -0,0 +1,143 @@ +package net.servicestack.idea.php; + +import com.intellij.openapi.module.Module; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; +import net.minidev.json.JSONObject; +import net.minidev.json.JSONValue; +import net.minidev.json.parser.ParseException; +import net.servicestack.idea.common.Analytics; +import net.servicestack.idea.common.DialogErrorMessages; +import net.servicestack.idea.common.IDEAUtils; +import net.servicestack.idea.common.INativeTypesHandler; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +public class AddPhpRefHandler { + static void handleOk(Module module, + String addressUrl, + String fileName, + String selectedDirectory, + StringBuilder errorMessage) { + File file = new File(selectedDirectory); + INativeTypesHandler nativeTypesHandler = + new PhpNativeTypesHandler(); + + String dtoPath = file.getAbsolutePath() + File.separator + + IDEAUtils.getDtoFileName(fileName, nativeTypesHandler); + List codeLines = getDtoLines(addressUrl, nativeTypesHandler, errorMessage); + + if (codeLines == null) { + return; + } + + tryUpdateComposerJson(module, errorMessage); + + if (!IDEAUtils.writeDtoFile(codeLines, dtoPath, errorMessage)) { + return; + } + + Analytics.SubmitAnonymousAddReferenceUsage(nativeTypesHandler); + IDEAUtils.refreshFile(module, dtoPath, true); + VirtualFileManager.getInstance().syncRefresh(); + } + + private static void tryUpdateComposerJson(Module module, StringBuilder errorMessage) { + VirtualFile[] roots = ModuleRootManager.getInstance(module).getContentRoots(); + for (VirtualFile root : roots) { + VirtualFile composerJsonFile = root.findChild("composer.json"); + + if (composerJsonFile != null) { + try { + Path path = Paths.get(composerJsonFile.getPath()); + String content = new String(Files.readAllBytes(path)); + + // Parse JSON content to JSONObject + JSONObject composerJson = (JSONObject) JSONValue.parseWithException(content); + + // Check if servicestack package is already added + if (composerJson.containsKey("require")) { + JSONObject requireSection = (JSONObject) composerJson.get("require"); + if (requireSection.containsKey("servicestack/client")) { + return; // Exit early if servicestack already exists + } + } + + // Add servicestack/client dependency via Composer Jetbrains APIs + // This is very inconsistent and doesn't always work + // Editing the `composer.json` manually causes errors from `composer`. + // Leaving this out until I can figure out a better way to do this. + // installPackage(module); + } catch (IOException | ParseException e) { + errorMessage.append(e.getMessage()); + e.printStackTrace(); + } + } + } + } + +// public static void installPackage(Module module) { +// // Retrieve the module's root manager +// ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module); +// +// // Retrieve the module's content roots +// VirtualFile[] roots = moduleRootManager.getContentRoots(); +// +// if (roots.length == 0) { +// Logger.getInstance(AddPhpRefHandler.class).warn("No content roots found"); +// return; +// } +// +// VirtualFile root = roots[0]; // Assuming first content root is the main project root +// String projectBasePath = root.getPath(); +// +// ApplicationManager.getApplication().executeOnPooledThread(() -> { +// GeneralCommandLine commandLine = new GeneralCommandLine(); +// commandLine.withWorkDirectory(projectBasePath); +// commandLine.setExePath("composer"); +// commandLine.addParameter("require"); +// commandLine.addParameter("servicestack/client"); +// +// try { +// commandLine.createProcess(); +// } catch (Exception e) { +// Logger.getInstance(AddPhpRefHandler.class).error(e); +// } +// }); +// } + + private static List getDtoLines(String addressUrl, INativeTypesHandler nativeTypesHandler, + StringBuilder errorMessage) { + List codeLines; + try { + codeLines = nativeTypesHandler.getUpdatedCode(addressUrl, null); + // append the first two lines and check if it equals the native types handler comment start stripped of whitespace + String firstLine = codeLines.get(0).replaceAll("\\s+", ""); + String secondLine = codeLines.get(1).replaceAll("\\s+", ""); + String commentStart = nativeTypesHandler.getOptionsCommentStart().replaceAll("\\s+", ""); + if (!(firstLine + secondLine).equals(commentStart)) { + //Invalid endpoint + errorMessage.append("The address url is not a valid ServiceStack endpoint."); + return null; + } + } catch (URISyntaxException | MalformedURLException | FileNotFoundException e) { + e.printStackTrace(); + DialogErrorMessages.appendInvalidEndpoint(errorMessage, addressUrl, e); + return null; + } catch (IOException e) { + e.printStackTrace(); + DialogErrorMessages.appendReadResponseError(errorMessage, addressUrl, e); + return null; + } + return codeLines; + } +} diff --git a/src/main/java/net/servicestack/idea/php/PhpNativeTypesHandler.java b/src/main/java/net/servicestack/idea/php/PhpNativeTypesHandler.java new file mode 100644 index 0000000..f2f476f --- /dev/null +++ b/src/main/java/net/servicestack/idea/php/PhpNativeTypesHandler.java @@ -0,0 +1,36 @@ +package net.servicestack.idea.php; + +import net.servicestack.idea.common.BaseNativeTypesHandler; +import net.servicestack.idea.common.NativeTypesLanguage; + +public class PhpNativeTypesHandler extends BaseNativeTypesHandler { + @Override + public String getFileExtension() { + return ".php"; + } + + @Override + public String getRelativeTypesUrl() { + return "types/php"; + } + + @Override + public NativeTypesLanguage getTypesLanguage() { + return NativeTypesLanguage.Php; + } + + @Override + public String getOptionsCommentStart() { + return " + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index b1ccb8e..b36f7dc 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -12,6 +12,7 @@ com.intellij.modules.lang com.intellij.modules.java com.intellij.modules.python + com.jetbrains.php