mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
+2
-2
@@ -5,6 +5,7 @@
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/scripts" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/restApiDocGenerator/node_modules" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
@@ -35,5 +36,4 @@
|
||||
<orderEntry type="module" module-name="groovy-jps-plugin" scope="RUNTIME" />
|
||||
<orderEntry type="module" module-name="groovy_rt" scope="RUNTIME" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
</module>
|
||||
@@ -0,0 +1 @@
|
||||
node_modules/
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "IntelliJ Platform REST API",
|
||||
"version": "140.2110",
|
||||
"url" : "http://localhost:63342/rest"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
var gulp = require('gulp')
|
||||
var apidoc = require('gulp-apidoc')
|
||||
var path = require('path')
|
||||
|
||||
var sources = path.normalize("../../platform/platform-impl/src/org/jetbrains/ide")
|
||||
|
||||
gulp.task('apidoc', function () {
|
||||
apidoc.exec({src: sources, dest: (process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE) + "/idea-rest-api"})
|
||||
})
|
||||
|
||||
gulp.task('default', ['apidoc'])
|
||||
|
||||
gulp.task('watch', function() {
|
||||
gulp.watch(sources + "/**/*.{clj,coffee,cs,dart,erl,go,java,js,php,py,rb,ts,pm}", ['apidoc'])
|
||||
})
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "restApiDocGenerator",
|
||||
"devDependencies": {
|
||||
"gulp": "^3.8.10",
|
||||
"gulp-apidoc": "^0.1.2"
|
||||
}
|
||||
}
|
||||
@@ -62,7 +62,10 @@ public class StubTree extends ObjectStubTree<StubElement<?>> {
|
||||
@NotNull
|
||||
@Override
|
||||
public List<StubElement<?>> getPlainListFromAllRoots() {
|
||||
return ContainerUtil.concat(getRoot().getStubRoots(), new Function<PsiFileStub, Collection<? extends StubElement<?>>>() {
|
||||
final PsiFileStub[] roots = getRoot().getStubRoots();
|
||||
if (roots.length == 1) return super.getPlainListFromAllRoots();
|
||||
|
||||
return ContainerUtil.concat(roots, new Function<PsiFileStub, Collection<? extends StubElement<?>>>() {
|
||||
@Override
|
||||
public Collection<? extends StubElement<?>> fun(PsiFileStub stub) {
|
||||
final ObjectStubTree existingTree = stub.getUserData(STUB_TO_TREE_REFERENCE);
|
||||
|
||||
@@ -219,14 +219,16 @@ public class JBScrollPane extends JScrollPane {
|
||||
if (hsb != null) container.setComponentZOrder(hsb, 0);
|
||||
|
||||
if (extendViewportUnderVScrollbar) {
|
||||
int x2 = Math.max(vsb.getX() + vsb.getWidth(), viewportBounds.x + viewportBounds.width);
|
||||
viewportBounds.x = Math.min(viewportBounds.x, vsb.getX());
|
||||
viewportBounds.width = vsb.getX() + vsb.getWidth() - viewportBounds.x;
|
||||
viewportBounds.width = x2 - viewportBounds.x;
|
||||
}
|
||||
if (extendViewportUnderHScrollbar) {
|
||||
int y2 = Math.max(hsb.getY() + hsb.getHeight(), viewportBounds.y + viewportBounds.height);
|
||||
viewportBounds.y = Math.min(viewportBounds.y, hsb.getY());
|
||||
viewportBounds.height = hsb.getY() + hsb.getHeight() - viewportBounds.y;
|
||||
viewportBounds.height = y2 - viewportBounds.y;
|
||||
}
|
||||
|
||||
|
||||
if (extendViewportUnderVScrollbar) {
|
||||
if (hsb != null) {
|
||||
Rectangle scrollbarBounds = hsb.getBounds();
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
###
|
||||
@apiDefine SuccessExample
|
||||
|
||||
@apiSuccessExample {json} Success-Response:
|
||||
{
|
||||
"name": "WebStorm 140.SNAPSHOT",
|
||||
"productName": "WebStorm",
|
||||
"baselineVersion": 140
|
||||
}
|
||||
###
|
||||
|
||||
###
|
||||
@apiDefine SuccessExampleWithRegisteredFileTypes
|
||||
|
||||
@apiSuccessExample {json} Success-Response (with registeredFileTypes):
|
||||
{
|
||||
"name": "WebStorm 140.SNAPSHOT",
|
||||
"productName": "WebStorm",
|
||||
"baselineVersion": 140,
|
||||
"registeredFileTypes": [
|
||||
{
|
||||
"name": "HTML",
|
||||
"description": "HTML files",
|
||||
"isBinary": false
|
||||
},
|
||||
{
|
||||
"name": "XHTML",
|
||||
"description": "XHTML files",
|
||||
"isBinary": false
|
||||
},
|
||||
{
|
||||
"name": "DTD",
|
||||
"description": "XML Document Type Definition",
|
||||
"isBinary": false
|
||||
},
|
||||
{
|
||||
"name": "XML",
|
||||
"description": "XML files",
|
||||
"isBinary": false
|
||||
}
|
||||
]
|
||||
}
|
||||
###
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* 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 org.jetbrains.ide;
|
||||
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import com.intellij.openapi.application.ApplicationInfo;
|
||||
import com.intellij.openapi.application.ApplicationNamesInfo;
|
||||
import com.intellij.openapi.application.ex.ApplicationInfoEx;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.FileTypeRegistry;
|
||||
import com.intellij.openapi.util.BuildNumber;
|
||||
import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.util.PlatformUtils;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.http.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.io.Responses;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
|
||||
/**
|
||||
* @api {get} /about The application info
|
||||
* @apiName about
|
||||
* @apiGroup Platform
|
||||
*
|
||||
* @apiParam {Boolean} [registeredFileTypes=false] Whether to include the list of registered file types.
|
||||
*
|
||||
* @apiSuccess {String} name The full application name.
|
||||
* @apiSuccess {String} productName The product name.
|
||||
* @apiSuccess {String} baselineVersion The baseline version.
|
||||
* @apiSuccess {String} [buildNumber] The build number.
|
||||
*
|
||||
* @apiSuccess {Object[]} registeredFileTypes The list of registered file types.
|
||||
* @apiSuccess {String} registeredFileTypes.name The name of file type.
|
||||
* @apiSuccess {String} registeredFileTypes.description The user-readable description of the file type.
|
||||
* @apiSuccess {Boolean} registeredFileTypes.isBinary Whether files of the specified type contain binary data.
|
||||
*
|
||||
* * @apiExample Request-Example:
|
||||
* /rest/about?registeredFileTypes
|
||||
*
|
||||
* @apiUse SuccessExample
|
||||
* @apiUse SuccessExampleWithRegisteredFileTypes
|
||||
*/
|
||||
class AboutHttpService extends RestService {
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getServiceName() {
|
||||
return "about";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isMethodSupported(@NotNull HttpMethod method) {
|
||||
return method == HttpMethod.GET;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String execute(@NotNull QueryStringDecoder urlDecoder, @NotNull FullHttpRequest request, @NotNull ChannelHandlerContext context) throws IOException {
|
||||
BuildNumber build = ApplicationInfo.getInstance().getBuild();
|
||||
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
|
||||
BufferExposingByteArrayOutputStream byteOut = new BufferExposingByteArrayOutputStream();
|
||||
JsonWriter writer = new JsonWriter(new OutputStreamWriter(byteOut, CharsetToolkit.UTF8_CHARSET));
|
||||
writer.beginObject();
|
||||
|
||||
String appName = ApplicationInfoEx.getInstanceEx().getFullApplicationName();
|
||||
if (!PlatformUtils.isIdeaUltimate()) {
|
||||
String productName = ApplicationNamesInfo.getInstance().getProductName();
|
||||
appName = appName.replace(productName + " (" + productName + ")", productName);
|
||||
if (appName.startsWith("JetBrains ")) {
|
||||
appName = appName.substring("JetBrains ".length());
|
||||
}
|
||||
}
|
||||
|
||||
writer.name("name").value(appName);
|
||||
writer.name("productName").value(ApplicationNamesInfo.getInstance().getProductName());
|
||||
writer.name("baselineVersion").value(build.getBaselineVersion());
|
||||
if (build.getBuildNumber() != Integer.MAX_VALUE) {
|
||||
writer.name("buildNumber").value(build.getBuildNumber());
|
||||
}
|
||||
|
||||
if (getBooleanParameter("registeredFileTypes", urlDecoder)) {
|
||||
writer.name("registeredFileTypes").beginArray();
|
||||
for (FileType fileType : FileTypeRegistry.getInstance().getRegisteredFileTypes()) {
|
||||
writer.beginObject();
|
||||
writer.name("name").value(fileType.getName());
|
||||
writer.name("description").value(fileType.getDescription());
|
||||
writer.name("isBinary").value(fileType.isBinary());
|
||||
writer.endObject();
|
||||
}
|
||||
writer.endArray();
|
||||
}
|
||||
|
||||
writer.endObject();
|
||||
writer.close();
|
||||
Responses.send(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer(byteOut.getInternalBuffer(), 0, byteOut.size())), context.channel(), request);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
###
|
||||
@apiDefine DiffRequestExample
|
||||
|
||||
@apiExample {json} Request-Example:
|
||||
{
|
||||
"fileType": "JSON",
|
||||
"contents": [
|
||||
{
|
||||
"title": "Actual",
|
||||
"content": "foo"
|
||||
},
|
||||
{
|
||||
"title": "Expected",
|
||||
"content": "bar"
|
||||
}
|
||||
]
|
||||
}
|
||||
###
|
||||
@@ -38,34 +38,57 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @api {post} /diff The differences between contents
|
||||
* @apiName diff
|
||||
* @apiGroup Platform
|
||||
*
|
||||
* @apiParam (properties) {String} [fileType] The file type name of the contents (see <a href="https://github.com/JetBrains/intellij-community/blob/master/platform/core-api/src/com/intellij/openapi/fileTypes/FileType.java">FileType.getName()</a>).
|
||||
* You can get registered file types using <a href="#api-Platform-about">/rest/about?registeredFileTypes</a> request.
|
||||
* @apiParam (properties) {String} [windowTitle=Diff Service] The title of the diff window.
|
||||
* @apiParam (properties) {Boolean} [focused=true] Whether to focus project window.
|
||||
*
|
||||
* @apiParam (properties) {Object[]{2..}} contents The list of the contents to diff.
|
||||
* @apiParam (properties) {String} [contents.title] The title of the content.
|
||||
* @apiParam (properties) {String} [contents.fileType] The file type name of the content.
|
||||
* @apiParam (properties) {String} contents.content The data of the content.
|
||||
*
|
||||
* @apiUse DiffRequestExample
|
||||
*/
|
||||
final class DiffHttpService extends RestService {
|
||||
@Override
|
||||
protected boolean isMethodSupported(@NotNull HttpMethod method) {
|
||||
return method == HttpMethod.POST;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getServiceName() {
|
||||
return "diff";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isMethodSupported(@NotNull HttpMethod method) {
|
||||
return method == HttpMethod.POST;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String execute(@NotNull QueryStringDecoder urlDecoder, @NotNull FullHttpRequest request, @NotNull ChannelHandlerContext context) throws IOException {
|
||||
final List<DiffContent> contents = new ArrayList<DiffContent>();
|
||||
final List<String> titles = new ArrayList<String>();
|
||||
|
||||
boolean focused = true;
|
||||
String windowTitle = null;
|
||||
JsonReader reader = createJsonReader(request);
|
||||
if (reader.hasNext()) {
|
||||
String fileType = null;
|
||||
boolean reformat;
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
String name = reader.nextName();
|
||||
if (name.equals("fileTypeName")) {
|
||||
if (name.equals("fileType")) {
|
||||
fileType = reader.nextString();
|
||||
}
|
||||
else if (name.equals("focused")) {
|
||||
focused = reader.nextBoolean();
|
||||
}
|
||||
else if (name.equals("windowTitle")) {
|
||||
windowTitle = StringUtil.nullize(reader.nextString(), true);
|
||||
}
|
||||
else if (name.equals("contents")) {
|
||||
String error = readContent(reader, contents, titles, fileType);
|
||||
if (error != null) {
|
||||
@@ -89,6 +112,8 @@ final class DiffHttpService extends RestService {
|
||||
return "No opened project, please open any project";
|
||||
}
|
||||
|
||||
final boolean finalFocused = focused;
|
||||
final String finalWindowTitle = windowTitle;
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -106,21 +131,23 @@ final class DiffHttpService extends RestService {
|
||||
|
||||
@Override
|
||||
public String getWindowTitle() {
|
||||
return "Diff Service";
|
||||
return StringUtil.notNullize(finalWindowTitle, "Diff Service");
|
||||
}
|
||||
});
|
||||
|
||||
ProjectUtil.focusProjectWindow(project, true);
|
||||
if (finalFocused) {
|
||||
ProjectUtil.focusProjectWindow(project, true);
|
||||
}
|
||||
}
|
||||
}, project.getDisposed());
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String readContent(@NotNull JsonReader reader, @NotNull List<DiffContent> contents, @NotNull List<String> titles, @Nullable String defaultFileTypeName) throws IOException {
|
||||
private static String readContent(@NotNull JsonReader reader, @NotNull List<DiffContent> contents, @NotNull List<String> titles, @Nullable String defaultfileType) throws IOException {
|
||||
FileTypeRegistry fileTypeRegistry = FileTypeRegistry.getInstance();
|
||||
|
||||
FileType defaultFileType = defaultFileTypeName == null ? null : fileTypeRegistry.findFileTypeByName(defaultFileTypeName);
|
||||
FileType defaultFileType = defaultfileType == null ? null : fileTypeRegistry.findFileTypeByName(defaultfileType);
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) {
|
||||
String title = null;
|
||||
@@ -133,7 +160,7 @@ final class DiffHttpService extends RestService {
|
||||
if (name.equals("title")) {
|
||||
title = reader.nextString();
|
||||
}
|
||||
else if (name.equals("fileTypeName")) {
|
||||
else if (name.equals("fileType")) {
|
||||
fileType = reader.nextString();
|
||||
}
|
||||
else if (name.equals("content")) {
|
||||
@@ -145,7 +172,7 @@ final class DiffHttpService extends RestService {
|
||||
}
|
||||
reader.endObject();
|
||||
|
||||
if (content == null) {;
|
||||
if (content == null) {
|
||||
return "content is not specified";
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.openapi.wm.IdeFrame;
|
||||
import com.intellij.util.ExceptionUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import io.netty.buffer.ByteBufInputStream;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.http.*;
|
||||
@@ -33,7 +34,12 @@ import org.jetbrains.io.Responses;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Document your service using <a href="http://apidocjs.com">apiDoc</a>. To extract big example from source code, consider to use *.coffee file near your source file.
|
||||
* (or Python/Ruby, but coffee recommended because it's plugin is lightweight). See {@link AboutHttpService} for example.
|
||||
*/
|
||||
public abstract class RestService extends HttpRequestHandler {
|
||||
protected static final Logger LOG = Logger.getInstance(RestService.class);
|
||||
|
||||
@@ -55,18 +61,21 @@ public abstract class RestService extends HttpRequestHandler {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
char c = uri.charAt(minLength + 1);
|
||||
char c = uri.charAt(minLength);
|
||||
return c == '/' || c == '?';
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected abstract boolean isMethodSupported(@NotNull HttpMethod method);
|
||||
|
||||
@NotNull
|
||||
/**
|
||||
* Use human-readable name or UUID if it is an internal service.
|
||||
*/
|
||||
protected abstract String getServiceName();
|
||||
|
||||
protected abstract boolean isMethodSupported(@NotNull HttpMethod method);
|
||||
|
||||
@Override
|
||||
public final boolean process(@NotNull QueryStringDecoder urlDecoder, @NotNull FullHttpRequest request, @NotNull ChannelHandlerContext context) throws IOException {
|
||||
try {
|
||||
@@ -115,4 +124,15 @@ public abstract class RestService extends HttpRequestHandler {
|
||||
}
|
||||
return project;
|
||||
}
|
||||
|
||||
protected static boolean getBooleanParameter(@NotNull String name, @NotNull QueryStringDecoder urlDecoder) {
|
||||
List<String> values = urlDecoder.parameters().get(name);
|
||||
if (ContainerUtil.isEmpty(values)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String value = values.get(values.size() - 1);
|
||||
// if just name specified, so, true
|
||||
return value.isEmpty() || Boolean.parseBoolean(value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,6 +341,7 @@
|
||||
<postStartupActivity implementation="org.jetbrains.ide.BuiltInServerManagerImpl$MyPostStartupActivity"/>
|
||||
|
||||
<httpRequestHandler implementation="org.jetbrains.ide.DiffHttpService"/>
|
||||
<httpRequestHandler implementation="org.jetbrains.ide.AboutHttpService"/>
|
||||
|
||||
<editorNotificationProvider implementation="com.intellij.openapi.editor.impl.ForcedSoftWrapsNotificationProvider"/>
|
||||
<editorNotificationProvider implementation="com.intellij.ide.FileChangedNotificationProvider"/>
|
||||
|
||||
Reference in New Issue
Block a user