├── .gitignore ├── .travis.yml ├── Features.txt ├── LICENSE ├── README.md ├── antlr ├── README.md ├── antlr.target ├── antlr4_local.target ├── build.properties ├── feature.xml ├── neon1-default.launch ├── site.xml └── sync_with_website.sh ├── developer-guide.md ├── images ├── 2016-02-21_marketplace.png ├── 2016-04-14_editor_and_outline.png ├── 2016-04-16_editor_and_quickoutline.png ├── 2016-04-20_editor_charset.png ├── YouTube-logo-small.png ├── logo-json-trans.png ├── logo-json-trans_eclipse.png └── logo-json.png ├── jsonedit-core ├── META-INF │ └── MANIFEST.MF ├── build.properties ├── plugin.xml ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── boothen │ └── jsonedit │ └── core │ ├── BundleUtils.java │ ├── JsonColorProvider.java │ ├── JsonCorePlugin.java │ ├── JsonLog.java │ └── preferences │ ├── JsonPreferenceInitializer.java │ ├── JsonPreferences.java │ └── TokenStyle.java ├── jsonedit-editor ├── META-INF │ └── MANIFEST.MF ├── build.properties ├── i18n │ └── Messages.properties ├── icons │ └── json.png ├── plugin.xml ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── boothen │ └── jsonedit │ └── editor │ ├── Activator.java │ ├── DocumentSetup.java │ ├── JsonInformationProvider.java │ ├── JsonNewFileWizard.java │ ├── JsonSourceViewer.java │ ├── JsonSourceViewerConfiguration.java │ ├── JsonTextEditor.java │ ├── Messages.java │ ├── RangeHighlighter.java │ └── model │ ├── JsonReconcilingStrategy.java │ └── ParseTreeComparator.java ├── jsonedit-feature ├── build.properties ├── feature.xml └── pom.xml ├── jsonedit-folding ├── META-INF │ └── MANIFEST.MF ├── build.properties ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── boothen │ └── jsonedit │ └── folding │ ├── FoldingVisitor.java │ └── JsonFoldingPositionsBuilder.java ├── jsonedit-model ├── .gitignore ├── META-INF │ └── MANIFEST.MF ├── build.properties ├── grammar │ ├── JSON.g4 │ ├── JSONLexer.g4 │ └── create_code.sh ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── boothen │ └── jsonedit │ ├── antlr │ ├── JSONBaseListener.java │ ├── JSONBaseVisitor.java │ ├── JSONLexer.java │ ├── JSONListener.java │ ├── JSONParser.java │ └── JSONVisitor.java │ ├── model │ ├── AntlrAdapter.java │ ├── AntlrTokenScanner.java │ ├── JsonContextTokenFinder.java │ ├── ParseProblem.java │ ├── ParseResult.java │ ├── ParseTreeInfo.java │ ├── Segment.java │ └── TokenStyler.java │ └── problems │ ├── DuplicateKeyFinder.java │ └── StringProblemFinder.java ├── jsonedit-outline ├── META-INF │ └── MANIFEST.MF ├── build.properties ├── icons │ ├── JsonArray.png │ ├── JsonBoolean.png │ ├── JsonError.png │ ├── JsonNull.png │ ├── JsonNumber.png │ ├── JsonObject.png │ └── JsonString.png ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── boothen │ └── jsonedit │ ├── outline │ ├── Activator.java │ ├── Container.java │ ├── JsonContentOutlinePage.java │ ├── JsonContentProvider.java │ ├── JsonContextImageVisitor.java │ ├── JsonContextLabelVisitor.java │ ├── JsonContextTreeFilter.java │ ├── JsonLabelProvider.java │ └── ParentProvider.java │ └── quickoutline │ ├── NamePatternFilter.java │ └── QuickOutlinePopup.java ├── jsonedit-preferences ├── META-INF │ └── MANIFEST.MF ├── build.properties ├── coloring_example.json ├── formatter_example.json ├── plugin.properties ├── plugin.xml ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── boothen │ └── jsonedit │ └── preferences │ ├── Activator.java │ ├── JsonRootPreferencePage.java │ ├── JsonTokenStyler.java │ ├── NodeType.java │ ├── OverlayPreferenceStore.java │ ├── colors │ └── JsonSyntaxColorsPreferencePage.java │ └── format │ ├── JsonContentFormatter.java │ ├── JsonFormatPreferencePage.java │ ├── JsonFormatStrategy.java │ ├── JsonFormatter.java │ └── JsonIndenter.java ├── jsonedit-repository └── pom.xml ├── jsonedit-site ├── .gitignore ├── category.xml ├── index.html ├── pom.xml ├── scripts │ ├── m-xml.js │ └── m-xml.min.js ├── site.xml ├── sync_with_folder.sh ├── sync_with_website.sh └── web │ ├── site.css │ └── site.xsl ├── jsonedit-test ├── META-INF │ └── MANIFEST.MF ├── build.properties ├── pom.xml ├── src │ └── main │ │ ├── java │ │ └── com │ │ │ └── boothen │ │ │ └── jsonedit │ │ │ └── core │ │ │ ├── ParseTreeSerializer.java │ │ │ ├── util │ │ │ └── FileToDocUtility.java │ │ │ └── validation │ │ │ └── JsonTextValidationTest.java │ │ └── resources │ │ ├── array.json │ │ ├── config.json │ │ ├── getMediaDetails_null_response.json │ │ ├── object.json │ │ ├── test.json │ │ ├── test1.json │ │ ├── test12.json │ │ ├── test13.json │ │ ├── test14.json │ │ ├── test15.json │ │ ├── test16.json │ │ ├── test17.json │ │ ├── test18.json │ │ ├── test19.json │ │ ├── test2.json │ │ ├── test20.json │ │ ├── test21.json │ │ ├── test22.json │ │ ├── test23.json │ │ ├── test24.json │ │ ├── test25.json │ │ ├── test26.json │ │ ├── test27.json │ │ ├── test28.json │ │ ├── test29.json │ │ ├── test3.json │ │ ├── test30.json │ │ ├── test31.json │ │ ├── test32.json │ │ ├── test33.json │ │ ├── test34.json │ │ ├── test35.json │ │ ├── test36.json │ │ ├── test37.json │ │ ├── test38.json │ │ ├── test39.json │ │ ├── test4.json │ │ ├── test40.json │ │ ├── test41.json │ │ ├── test42.json │ │ ├── test43.json │ │ ├── test44.json │ │ ├── test45.json │ │ ├── test46.json │ │ ├── test47.json │ │ ├── test48.json │ │ ├── test49.json │ │ ├── test5.json │ │ ├── test6.json │ │ ├── test7.json │ │ ├── test8.json │ │ └── test9.json └── test.json ├── jsonedit-text ├── META-INF │ └── MANIFEST.MF ├── build.properties ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── boothen │ └── jsonedit │ └── text │ └── PositionVisitor.java ├── org.sourceforge.jsonedit.core ├── .gitignore └── src │ └── org │ └── sourceforge │ └── jsonedit │ └── core │ └── prefs │ └── PreferenceInitializer.java ├── org.sourceforge.jsonedit.feature └── .gitignore ├── org.sourceforge.jsonedit.test └── .gitignore ├── pom.xml └── release-process.md /.gitignore: -------------------------------------------------------------------------------- 1 | .settings/ 2 | target/ 3 | .project 4 | .classpath 5 | bin/ 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | -------------------------------------------------------------------------------- /Features.txt: -------------------------------------------------------------------------------- 1 | Road map 2 | ======== 3 | 4 | Multi objects in file 5 | 6 | - JsonReconcilingStrategy 7 | - Text Folding 8 | - JsonTextFormatter 9 | 10 | Fix \" in values 11 | Fix validation. 12 | Fix multi object outline issue. 13 | 14 | Pair matching in editor {} or [] goes a miss if String contains any of those characters. 15 | 16 | ctrl-f to format 17 | when formatting don't remove trailing space 18 | allow formatting to include whitespace before and after colon. 19 | 20 | allow folding to be turned off 21 | 22 | 23 | 24 | 25 | Single file validation 26 | Single error outline 27 | 28 | Allow editor to open for .js ending + validation 29 | UTF-8 characters not show in outline 30 | 31 | Multi errors in outline 32 | Multi errors in validation 33 | Generate Java objects 34 | Mock JSON from Java Object 35 | Http Client 36 | Get incorporated into Eclipse Color Themes 37 | Fix coloring for String value with space after : 38 | 39 | 40 | JSON Schema 41 | Upgrade to 4.2 42 | 43 | 44 | Current Features 45 | ================ 46 | 47 | 1) Outline 48 | 2) Text Coloring 49 | 3) Project Validation 50 | 4) Text format 51 | 5) Text folding 52 | 53 | 54 | 0.9.8 55 | ===== 56 | 57 | 1) Multi objects in file. 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Eclipse Json Editor Plugin 2 | ======================= 3 | 4 | [![epl10](https://img.shields.io/badge/EPL-1.0-blue.svg "Eclipse Public License 1.0")](https://www.eclipse.org/legal/epl-v10.html) 5 | [![GitHub tag](https://img.shields.io/github/tag/boothen/Json-Eclipse-Plugin.svg)]() 6 | [![Build Status](https://travis-ci.org/boothen/Json-Eclipse-Plugin.svg?branch=master)](http://travis-ci.org/boothen/Json-Eclipse-Plugin) 7 | 8 | ![screenshot](images/2016-04-16_editor_and_quickoutline.png "eclipse Screenshot") 9 | 10 | This plugin adds support for JSON files to eclipse. You can install the latest version directly from this update site: 11 | 12 | http://boothen.github.io/Json-Eclipse-Plugin/ 13 | 14 | You can also get this plugin from the [eclipse Marketplace](https://marketplace.eclipse.org/content/json-editor-plugin). 15 | 16 | A small video demonstration is [available on YouTube](https://www.youtube.com/watch?v=vXRwFwk2QE4) 17 | 18 | Features 19 | --------------------- 20 | 21 | * Supports every eclipse flavor (JavaEE, CDT, RCP, you name it!) 22 | * Supports eclipse version 3.7 - 2019-12-R and most probably later versions 23 | * Conforms to the JSON standard as defined in the [RFC 4627](https://tools.ietf.org/html/rfc4627) by D. Crockford 24 | * Deep Integration (File wizards, tree outline, preference pages) 25 | * Quick Outline with reg-ex support `(CTRL + O)` 26 | * Highly configurable code formatting `(CTRL + SHIFT + F)` 27 | * Custom syntax highlighting 28 | * Text folding and range highlighters 29 | * Detects duplicate keys 30 | * Reliable, resilient and fast syntax tree parsing and validation through ANTLR 4 31 | * Available for free - that's a feature, isn't it? 32 | 33 | Developer Guides 34 | --------------------- 35 | See this [getting started page](developer-guide.md) or the [release management cheat sheet](release-process.md). 36 | 37 | License 38 | --------------------- 39 | This software is licensed in compliance with the eclipse Foundation under the [eclipse Public License 1.0](https://www.eclipse.org/legal/epl-v10.html). 40 | 41 | SourceForge 42 | --------------------- 43 | 44 | This plugin was formerly hosted at https://sourceforge.net/projects/eclipsejsonedit/ 45 | 46 | -------------------------------------------------------------------------------- /antlr/README.md: -------------------------------------------------------------------------------- 1 | ## How-to generate the certificate for let's encrypt 2 | 3 | openssl pkcs12 -export -out certificate.pfx -inkey privkey.pem -in cert.pem -certfile chain.pem 4 | 5 | 6 | ## Sign jar files manually 7 | 8 | jarsigner -storetype pkcs12 -keystore /e/Github/certificate.pfx -tsa http://zeitstempel.dfn.de org.antlr.antlr4-runtime_4.7.1.jar 1 9 | 10 | -------------------------------------------------------------------------------- /antlr/antlr.target: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /antlr/antlr4_local.target: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /antlr/build.properties: -------------------------------------------------------------------------------- 1 | bin.includes = feature.xml 2 | -------------------------------------------------------------------------------- /antlr/feature.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | ANTLR (ANother Tool for Language Recognition) is a powerful parser generator for reading, processing, executing, or translating structured text or binary files. It's widely used to build languages, tools, and frameworks. From a grammar, ANTLR generates a parser that can build and walk parse trees. 10 | 11 | 12 | 13 | [The "BSD license"] 14 | Copyright (c) 2015 Terence Parr, Sam Harwell 15 | All rights reserved. 16 | Redistribution and use in source and binary forms, with or without 17 | modification, are permitted provided that the following conditions 18 | are met: 19 | 1. Redistributions of source code must retain the above copyright 20 | notice, this list of conditions and the following disclaimer. 21 | 2. Redistributions in binary form must reproduce the above copyright 22 | notice, this list of conditions and the following disclaimer 23 | in the 24 | documentation and/or other materials provided with the distribution. 25 | 3. The name of the author may not be used to endorse or promote 26 | products 27 | derived from this software without specific prior written permission. 28 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 29 | OR 30 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 31 | WARRANTIES 32 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 33 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 34 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 35 | BUT 36 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 37 | LOSS OF USE, 38 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 39 | ON ANY 40 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 41 | TORT 42 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 43 | THE USE OF 44 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 45 | 46 | 47 | 48 | [The "BSD license"] 49 | Copyright (c) 2015 Terence Parr, Sam Harwell 50 | All rights reserved. 51 | Redistribution and use in source and binary forms, with or without 52 | modification, are permitted provided that the following conditions 53 | are met: 54 | 1. Redistributions of source code must retain the above copyright 55 | notice, this list of conditions and the following disclaimer. 56 | 2. Redistributions in binary form must reproduce the above copyright 57 | notice, this list of conditions and the following disclaimer 58 | in the 59 | documentation and/or other materials provided with the distribution. 60 | 3. The name of the author may not be used to endorse or promote 61 | products 62 | derived from this software without specific prior written permission. 63 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 64 | OR 65 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 66 | WARRANTIES 67 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 68 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 69 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 70 | BUT 71 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 72 | LOSS OF USE, 73 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 74 | ON ANY 75 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 76 | TORT 77 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 78 | THE USE OF 79 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 80 | 81 | 82 | 88 | 89 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /antlr/neon1-default.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /antlr/site.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /antlr/sync_with_website.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 3 | SITE=$SCRIPT_DIR 4 | TARGET="martin-steiger.de:/var/www/html/antlr47-signed" 5 | 6 | echo "Copying p2 update site content.." 7 | scp -p -r $SITE/*.jar $SITE/site.xml $SITE/features $SITE/plugins $TARGET 8 | 9 | # read -r raw input - disables interpretion of backslash escapes and line-continuation in the read data 10 | # read -p the prompt string is output 11 | # read -s to hide typed chars 12 | 13 | read -r -p "Press [ENTER] to exit..." 14 | 15 | 16 | -------------------------------------------------------------------------------- /developer-guide.md: -------------------------------------------------------------------------------- 1 | ## Setup 2 | 3 | * Go to https://www.eclipse.org/downloads and download an eclipse version with RCP support. Download and launch. 4 | * Import existing eclipse projects from the root folder of this repository. 5 | * The ANTLR dependencies will be unresolvable, because the default target platform definition does not include it. 6 | Select `antlr.target` in the antlr project set it as Target Platform. 7 | To update the ANTLR version on the remote site, [reficio's p2-maven-plugin](https://github.com/reficio/p2-maven-plugin) can be used. 8 | Alternatively, the site file from the same folder can be used from eclipse to create a new p2 update site. 9 | * Create a new launch configuration with default settings. That mean that the product is `org.eclipse.platform.ide` and 10 | includes all workspace and enabled target plugins. No custom settings are required. 11 | * Run or debug the application as needed 12 | -------------------------------------------------------------------------------- /images/2016-02-21_marketplace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boothen/Json-Eclipse-Plugin/68da2e573116f3e452066db9d985dff48638d88e/images/2016-02-21_marketplace.png -------------------------------------------------------------------------------- /images/2016-04-14_editor_and_outline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boothen/Json-Eclipse-Plugin/68da2e573116f3e452066db9d985dff48638d88e/images/2016-04-14_editor_and_outline.png -------------------------------------------------------------------------------- /images/2016-04-16_editor_and_quickoutline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boothen/Json-Eclipse-Plugin/68da2e573116f3e452066db9d985dff48638d88e/images/2016-04-16_editor_and_quickoutline.png -------------------------------------------------------------------------------- /images/2016-04-20_editor_charset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boothen/Json-Eclipse-Plugin/68da2e573116f3e452066db9d985dff48638d88e/images/2016-04-20_editor_charset.png -------------------------------------------------------------------------------- /images/YouTube-logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boothen/Json-Eclipse-Plugin/68da2e573116f3e452066db9d985dff48638d88e/images/YouTube-logo-small.png -------------------------------------------------------------------------------- /images/logo-json-trans.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boothen/Json-Eclipse-Plugin/68da2e573116f3e452066db9d985dff48638d88e/images/logo-json-trans.png -------------------------------------------------------------------------------- /images/logo-json-trans_eclipse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boothen/Json-Eclipse-Plugin/68da2e573116f3e452066db9d985dff48638d88e/images/logo-json-trans_eclipse.png -------------------------------------------------------------------------------- /images/logo-json.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boothen/Json-Eclipse-Plugin/68da2e573116f3e452066db9d985dff48638d88e/images/logo-json.png -------------------------------------------------------------------------------- /jsonedit-core/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Bundle-ManifestVersion: 2 3 | Bundle-Name: JSON Editor Core 4 | Bundle-SymbolicName: jsonedit-core;singleton:=true 5 | Bundle-Version: 1.1.3 6 | Bundle-Activator: com.boothen.jsonedit.core.JsonCorePlugin 7 | Require-Bundle: org.eclipse.ui, 8 | org.eclipse.core.runtime, 9 | org.eclipse.jface.text, 10 | org.eclipse.core.resources, 11 | org.eclipse.ui.editors, 12 | org.eclipse.ui.ide, 13 | org.eclipse.ui.views 14 | Bundle-ActivationPolicy: lazy 15 | Bundle-RequiredExecutionEnvironment: JavaSE-1.7 16 | Bundle-Vendor: Boothen Technology 17 | Export-Package: com.boothen.jsonedit.core, 18 | com.boothen.jsonedit.core.preferences 19 | -------------------------------------------------------------------------------- /jsonedit-core/build.properties: -------------------------------------------------------------------------------- 1 | source.. = src/main/java 2 | output.. = target/classes 3 | bin.includes = META-INF/,\ 4 | .,\ 5 | plugin.xml 6 | -------------------------------------------------------------------------------- /jsonedit-core/plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /jsonedit-core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | 7 | com.boothen 8 | jsonedit-parent 9 | 1.1.3 10 | 11 | 12 | jsonedit-core 13 | eclipse-plugin 14 | 15 | 16 | -------------------------------------------------------------------------------- /jsonedit-core/src/main/java/com/boothen/jsonedit/core/BundleUtils.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.core; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | import java.nio.charset.Charset; 6 | import java.nio.charset.StandardCharsets; 7 | import java.util.Scanner; 8 | 9 | import org.osgi.framework.Bundle; 10 | 11 | /** 12 | * TODO: describe 13 | */ 14 | public final class BundleUtils { 15 | 16 | private BundleUtils() { 17 | // no instances 18 | } 19 | 20 | /** 21 | * Uses UTF-8 character encoding 22 | * @param bundle the bundle that contains the text resource 23 | * @param path the path of the resource 24 | * @return the content as string (including line delimiters) 25 | * @throws IOException if the resource cannot be read 26 | */ 27 | public static String readFile(Bundle bundle, String path) throws IOException { 28 | return readFile(bundle, path, StandardCharsets.UTF_8); 29 | } 30 | 31 | /** 32 | * @param bundle the bundle that contains the text resource 33 | * @param path the path of the resource 34 | * @param cs the character set to use 35 | * @return the content as string (including line delimiters) 36 | * @throws IOException if the resource cannot be read 37 | */ 38 | public static String readFile(Bundle bundle, String path, Charset cs) throws IOException { 39 | URL jsonUrl = bundle.getEntry(path); 40 | try (Scanner scanner = new Scanner(jsonUrl.openStream(), cs.name())) { 41 | scanner.useDelimiter("\\A"); 42 | if (scanner.hasNext()) { 43 | return scanner.next(); 44 | } else { 45 | throw new IOException("no content"); 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /jsonedit-core/src/main/java/com/boothen/jsonedit/core/JsonColorProvider.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2014 Boothen Technology Ltd. 3 | * 4 | * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://eclipse.org/org/documents/epl-v10.html 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *******************************************************************************/ 16 | /** 17 | * 18 | */ 19 | package com.boothen.jsonedit.core; 20 | 21 | import java.util.HashMap; 22 | import java.util.Iterator; 23 | import java.util.Map; 24 | 25 | import org.eclipse.swt.graphics.Color; 26 | import org.eclipse.swt.graphics.RGB; 27 | import org.eclipse.swt.widgets.Display; 28 | 29 | /** 30 | * Provides the coloring for the text editor. 31 | * 32 | * @author Matt Garner 33 | * 34 | */ 35 | public final class JsonColorProvider { 36 | 37 | private final Map fColorTable = new HashMap(); 38 | 39 | JsonColorProvider() { 40 | // package private 41 | } 42 | 43 | /** 44 | * Release all of the color resources held onto by the receiver. 45 | */ 46 | void purge() { 47 | Iterator e = fColorTable.values().iterator(); 48 | while (e.hasNext()) { 49 | e.next().dispose(); 50 | } 51 | fColorTable.clear(); 52 | } 53 | 54 | /** 55 | * Return the color that is stored in the color table under the given RGB 56 | * value. 57 | * 58 | * @param rgb the RGB value 59 | * @return the color stored in the color table for the given RGB value 60 | */ 61 | public Color getColor(RGB rgb) { 62 | if (rgb == null) { 63 | return null; 64 | } 65 | 66 | Color color = fColorTable.get(rgb); 67 | 68 | if (color == null) { 69 | color = new Color(Display.getCurrent(), rgb); 70 | fColorTable.put(rgb, color); 71 | } 72 | 73 | return color; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /jsonedit-core/src/main/java/com/boothen/jsonedit/core/JsonCorePlugin.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2014 Boothen Technology Ltd. 3 | * 4 | * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://eclipse.org/org/documents/epl-v10.html 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *******************************************************************************/ 16 | package com.boothen.jsonedit.core; 17 | 18 | 19 | import org.eclipse.jface.resource.ImageDescriptor; 20 | import org.eclipse.ui.plugin.AbstractUIPlugin; 21 | import org.osgi.framework.BundleContext; 22 | 23 | /** 24 | * Main plug class that integrates with Eclipse. 25 | * The plugin is a singleton and only one instance exists at a time. 26 | * @author Matt Garner 27 | * 28 | */ 29 | public class JsonCorePlugin extends AbstractUIPlugin { 30 | 31 | /** 32 | * The plug-in ID 33 | */ 34 | // public static final String PLUGIN_ID = "com.boothen.jsonedit.core"; 35 | public static final String PLUGIN_ID = "jsonedit-core"; 36 | 37 | private static final JsonColorProvider colorProvider = new JsonColorProvider(); 38 | 39 | private static JsonCorePlugin plugin; 40 | 41 | @Override 42 | public void start(BundleContext context) throws Exception { 43 | super.start(context); 44 | plugin = this; 45 | } 46 | 47 | @Override 48 | public void stop(BundleContext context) throws Exception { 49 | super.stop(context); 50 | colorProvider.purge(); 51 | plugin = null; 52 | } 53 | 54 | /** 55 | * Returns the shared instance 56 | * @return the shared instance 57 | */ 58 | public static JsonCorePlugin getDefault() { 59 | return plugin; 60 | } 61 | 62 | /** 63 | * Returns an image descriptor for the image file at the given plug-in relative path 64 | * @param path the path 65 | * @return the image descriptor 66 | */ 67 | public static ImageDescriptor getImageDescriptor(String path) { 68 | return imageDescriptorFromPlugin(PLUGIN_ID, path); 69 | } 70 | 71 | /** 72 | * @return the color manager/provider 73 | */ 74 | public static JsonColorProvider getColorProvider() { 75 | return colorProvider; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /jsonedit-core/src/main/java/com/boothen/jsonedit/core/JsonLog.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2014 Boothen Technology Ltd. 3 | * 4 | * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://eclipse.org/org/documents/epl-v10.html 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *******************************************************************************/ 16 | package com.boothen.jsonedit.core; 17 | 18 | import org.eclipse.core.runtime.IStatus; 19 | import org.eclipse.core.runtime.Status; 20 | import org.eclipse.ui.statushandlers.StatusManager; 21 | 22 | /** 23 | * Logging helper class. 24 | * 25 | * @author Matt Garner 26 | * 27 | */ 28 | public class JsonLog { 29 | 30 | /** 31 | * Log info method. 32 | * @param message the message to log 33 | */ 34 | public static void logInfo(String message) { 35 | report(IStatus.INFO, IStatus.OK, message, null); 36 | } 37 | 38 | /** 39 | * Log error method. 40 | * @param exception the exception to log (can be null) 41 | */ 42 | public static void logError(Throwable exception) { 43 | logError("Unexpected Exception", exception); 44 | } 45 | 46 | /** 47 | * Log error method. 48 | * @param message the message to log 49 | * @param exception the linked exception (can be null) 50 | */ 51 | public static void logError(String message, Throwable exception) { 52 | report(IStatus.ERROR, IStatus.OK, message, exception); 53 | } 54 | 55 | private static void report(int severity, int code, String message, Throwable orgException) { 56 | String pluginId = JsonCorePlugin.PLUGIN_ID; 57 | Throwable exception = orgException; 58 | if (exception == null) { 59 | // this will provide the stack trace 60 | exception = new RuntimeException(); 61 | } 62 | Status status = new Status(severity, pluginId, code, message, exception); 63 | StatusManager.getManager().handle(status, StatusManager.LOG); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /jsonedit-core/src/main/java/com/boothen/jsonedit/core/preferences/JsonPreferenceInitializer.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2014 Boothen Technology Ltd. 3 | * 4 | * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://eclipse.org/org/documents/epl-v10.html 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *******************************************************************************/ 16 | package com.boothen.jsonedit.core.preferences; 17 | 18 | import static com.boothen.jsonedit.core.preferences.JsonPreferences.AUTO_FORMAT_ON_SAVE; 19 | import static com.boothen.jsonedit.core.preferences.JsonPreferences.EDITOR_MATCHING_BRACKETS; 20 | import static com.boothen.jsonedit.core.preferences.JsonPreferences.EDITOR_MATCHING_BRACKETS_COLOR; 21 | import static com.boothen.jsonedit.core.preferences.JsonPreferences.EDITOR_TRAILING_NEWLINE; 22 | 23 | import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; 24 | import org.eclipse.jface.preference.IPreferenceStore; 25 | import org.eclipse.jface.resource.StringConverter; 26 | import org.eclipse.swt.graphics.RGB; 27 | 28 | import com.boothen.jsonedit.core.JsonCorePlugin; 29 | 30 | /** 31 | * 32 | * @author Matt Garner 33 | * 34 | */ 35 | public class JsonPreferenceInitializer extends AbstractPreferenceInitializer { 36 | 37 | @Override 38 | public void initializeDefaultPreferences() { 39 | // IEclipsePreferences node = DefaultScope.INSTANCE.getNode(JsonPreferencesPlugin.PLUGIN_ID); 40 | IPreferenceStore node = JsonCorePlugin.getDefault().getPreferenceStore(); 41 | 42 | node.setDefault(AUTO_FORMAT_ON_SAVE, false); 43 | node.setDefault(EDITOR_TRAILING_NEWLINE, true); 44 | node.setDefault(EDITOR_MATCHING_BRACKETS, true); 45 | node.setDefault(EDITOR_MATCHING_BRACKETS_COLOR, colorToString(0, 128, 0)); 46 | 47 | // See com.boothen.jsonedit.preferences.format.JsonFormatter.Affix for valid values 48 | node.setDefault("BEGIN_ARRAY.suffix", "NEWLINE"); 49 | node.setDefault("BEGIN_OBJECT.suffix", "NEWLINE"); 50 | node.setDefault("COLON.suffix", "SPACE"); 51 | node.setDefault("COMMA.suffix", "NEWLINE"); 52 | node.setDefault("END_OBJECT.prefix", "NEWLINE"); 53 | node.setDefault("END_ARRAY.prefix", "NEWLINE"); 54 | 55 | node.setDefault(TokenStyle.KEY.color(), colorToString(64, 128, 64)); 56 | node.setDefault(TokenStyle.TEXT.color(), colorToString(16, 0, 160)); 57 | node.setDefault(TokenStyle.NULL.color(), colorToString(0, 0, 0)); 58 | node.setDefault(TokenStyle.BOOLEAN.color(), colorToString(0, 0, 0)); 59 | node.setDefault(TokenStyle.NUMBER.color(), colorToString(16, 0, 160)); 60 | node.setDefault(TokenStyle.COMMENT.color(), colorToString(16, 128, 16)); 61 | node.setDefault(TokenStyle.ERROR.color(), colorToString(224, 0, 0)); 62 | 63 | node.setDefault(TokenStyle.NULL.isBold(), true); 64 | node.setDefault(TokenStyle.BOOLEAN.isBold(), true); 65 | } 66 | 67 | private static String colorToString(int red, int green, int blue) { 68 | return StringConverter.asString(new RGB(red, green, blue)); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /jsonedit-core/src/main/java/com/boothen/jsonedit/core/preferences/JsonPreferences.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.core.preferences; 2 | 3 | /** 4 | * Defines preference constants. 5 | */ 6 | public final class JsonPreferences { 7 | public static final String EDITOR_TRAILING_NEWLINE = "trailingNewline"; //$NON-NLS-1$ 8 | public static final String EDITOR_MATCHING_BRACKETS = "matchingBrackets"; //$NON-NLS-1l$ 9 | public static final String EDITOR_MATCHING_BRACKETS_COLOR = "matchingBracketsColor"; //$NON-NLS-1$ 10 | public static final String AUTO_FORMAT_ON_SAVE = "autoFormatOnSave"; //$NON-NLS-1$ 11 | 12 | private JsonPreferences() { 13 | // no instances 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /jsonedit-core/src/main/java/com/boothen/jsonedit/core/preferences/TokenStyle.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.core.preferences; 2 | 3 | /** 4 | * Defines the preference keys that are used in preference stores to acquire token-related settings. 5 | */ 6 | public enum TokenStyle { 7 | 8 | /** 9 | * The default style (used for commas, colons, etc) 10 | */ 11 | DEFAULT, 12 | 13 | /** 14 | * A key text string 15 | */ 16 | KEY, 17 | 18 | /** 19 | * A text string 20 | */ 21 | TEXT, 22 | 23 | /** 24 | * A number, either integer or floating point 25 | */ 26 | NUMBER, 27 | 28 | /** 29 | * A boolean value 30 | */ 31 | BOOLEAN, 32 | 33 | /** 34 | * The constant null. 35 | */ 36 | NULL, 37 | 38 | /** 39 | * A text comment node 40 | */ 41 | COMMENT, 42 | 43 | /** 44 | * An error node 45 | */ 46 | ERROR; 47 | 48 | /** 49 | * @return style + name in PascalCase 50 | */ 51 | public String base() { 52 | String name = name(); 53 | return "style" + name.charAt(0) + name.substring(1).toLowerCase(); 54 | } 55 | 56 | /** 57 | * @return the key separator 58 | */ 59 | public String separator() { 60 | return "."; 61 | } 62 | 63 | /** 64 | * @return the color key 65 | */ 66 | public String color() { 67 | return base() + separator() + "color"; 68 | } 69 | 70 | /** 71 | * @return the key that indicates if the style requires bold font 72 | */ 73 | public String isBold() { 74 | return base() + separator() + "isBold"; 75 | } 76 | 77 | /** 78 | * @return the key that indicates if the style requires italic font 79 | */ 80 | public String isItalic() { 81 | return base() + separator() + "isItalic"; 82 | } 83 | 84 | /** 85 | * The key, written in PascalCase 86 | */ 87 | @Override 88 | public String toString() { 89 | String name = name(); 90 | return name.charAt(0) + name.substring(1).toLowerCase(); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /jsonedit-editor/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Bundle-ManifestVersion: 2 3 | Bundle-Name: JSON Editor 4 | Bundle-SymbolicName: jsonedit-editor;singleton:=true 5 | Bundle-Version: 1.1.3 6 | Bundle-Activator: com.boothen.jsonedit.editor.Activator 7 | Require-Bundle: jsonedit-core, 8 | jsonedit-folding, 9 | jsonedit-model, 10 | jsonedit-preferences, 11 | jsonedit-text, 12 | jsonedit-outline, 13 | org.eclipse.ui.editors, 14 | org.eclipse.text, 15 | org.eclipse.core.runtime, 16 | org.eclipse.jface, 17 | org.eclipse.jface.text, 18 | org.eclipse.ui, 19 | org.eclipse.core.resources, 20 | org.eclipse.ui.views, 21 | org.eclipse.equinox.preferences, 22 | org.eclipse.ui.workbench, 23 | org.eclipse.ui.ide, 24 | org.eclipse.ui.workbench.texteditor, 25 | org.antlr.antlr4-runtime 26 | Bundle-RequiredExecutionEnvironment: JavaSE-1.7 27 | Bundle-ActivationPolicy: lazy 28 | Bundle-Vendor: Boothen Technology 29 | Export-Package: com.boothen.jsonedit.editor 30 | -------------------------------------------------------------------------------- /jsonedit-editor/build.properties: -------------------------------------------------------------------------------- 1 | source.. = src/main/java 2 | output.. = target/classes/ 3 | bin.includes = META-INF/,\ 4 | .,\ 5 | plugin.xml,\ 6 | icons/,\ 7 | i18n/ 8 | src.includes = i18n/ 9 | -------------------------------------------------------------------------------- /jsonedit-editor/i18n/Messages.properties: -------------------------------------------------------------------------------- 1 | #Eclipse messages class 2 | ShowOutline.label= Quick Outline 3 | ShowOutline.tooltip= Shows the Quick Outline of Editor Input 4 | ShowOutline.description= Shows the quick outline for the editor input 5 | 6 | Format.label=&Format 7 | Format.tooltip=Format the Selected Text 8 | Format.description=Format the selected text 9 | -------------------------------------------------------------------------------- /jsonedit-editor/icons/json.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boothen/Json-Eclipse-Plugin/68da2e573116f3e452066db9d985dff48638d88e/jsonedit-editor/icons/json.png -------------------------------------------------------------------------------- /jsonedit-editor/plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 15 | 17 | 18 | 19 | 20 | 22 | 26 | 27 | 31 | 32 | 33 | 35 | 37 | 40 | 42 | 44 | 46 | 47 | 48 | 49 | 50 | 51 | 53 | 56 | 58 | 60 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 72 | 74 | 75 | 77 | 78 | 80 | 81 | 82 | 83 | 86 | 87 | 93 | 94 | 95 | 96 | 98 | 104 | 105 | 107 | 112 | 117 | 118 | 119 | 123 | 124 | 125 | 127 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /jsonedit-editor/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | 7 | com.boothen 8 | jsonedit-parent 9 | 1.1.3 10 | 11 | 12 | jsonedit-editor 13 | eclipse-plugin 14 | 15 | 16 | -------------------------------------------------------------------------------- /jsonedit-editor/src/main/java/com/boothen/jsonedit/editor/Activator.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.editor; 2 | 3 | import org.eclipse.swt.widgets.Display; 4 | import org.eclipse.ui.PlatformUI; 5 | import org.eclipse.ui.plugin.AbstractUIPlugin; 6 | import org.osgi.framework.BundleContext; 7 | 8 | /** 9 | * The activator class controls the plug-in life cycle 10 | */ 11 | public class Activator extends AbstractUIPlugin { 12 | 13 | /** 14 | * The plug-in ID 15 | */ 16 | public static final String PLUGIN_ID = "jsonedit-editor"; //$NON-NLS-1$ 17 | 18 | /** 19 | * The shared instance 20 | */ 21 | private static Activator plugin; 22 | 23 | /** 24 | * The constructor 25 | */ 26 | public Activator() { 27 | if (PlatformUI.isWorkbenchRunning() || Display.getCurrent() != null) { 28 | getImageRegistry(); 29 | } 30 | } 31 | 32 | @Override 33 | public void start(BundleContext context) throws Exception { 34 | super.start(context); 35 | plugin = this; 36 | } 37 | 38 | @Override 39 | public void stop(BundleContext context) throws Exception { 40 | plugin = null; 41 | super.stop(context); 42 | } 43 | 44 | /** 45 | * Returns the shared instance 46 | * @return the shared instance 47 | */ 48 | public static Activator getDefault() { 49 | return plugin; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /jsonedit-editor/src/main/java/com/boothen/jsonedit/editor/DocumentSetup.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.editor; 2 | 3 | import org.eclipse.core.filebuffers.IDocumentSetupParticipant; 4 | import org.eclipse.jface.text.DefaultPositionUpdater; 5 | import org.eclipse.jface.text.IDocument; 6 | import org.eclipse.jface.text.IPositionUpdater; 7 | 8 | /** 9 | * Registers a position updater that tracks changes for the {@link JsonTextEditor#JSON_CATEGORY} positions. 10 | * This class is managed through an extension point. 11 | */ 12 | public class DocumentSetup implements IDocumentSetupParticipant { 13 | 14 | private final IPositionUpdater updater = new DefaultPositionUpdater(JsonTextEditor.JSON_CATEGORY); 15 | 16 | @Override 17 | public void setup(IDocument document) { 18 | document.addPositionCategory(JsonTextEditor.JSON_CATEGORY); 19 | document.addPositionUpdater(updater); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /jsonedit-editor/src/main/java/com/boothen/jsonedit/editor/JsonInformationProvider.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.editor; 2 | 3 | import java.io.IOException; 4 | import java.io.Reader; 5 | import java.io.StringReader; 6 | 7 | import org.eclipse.jface.text.IRegion; 8 | import org.eclipse.jface.text.ITextViewer; 9 | import org.eclipse.jface.text.Region; 10 | import org.eclipse.jface.text.information.IInformationProvider; 11 | import org.eclipse.jface.text.information.IInformationProviderExtension; 12 | 13 | import com.boothen.jsonedit.antlr.JSONParser.JsonContext; 14 | import com.boothen.jsonedit.core.JsonLog; 15 | import com.boothen.jsonedit.model.AntlrAdapter; 16 | import com.boothen.jsonedit.model.ParseResult; 17 | 18 | /** 19 | * Computes a JSON syntax tree (e.g. for the quick outline view) 20 | */ 21 | class JsonInformationProvider implements IInformationProvider, IInformationProviderExtension { 22 | 23 | @Override 24 | public IRegion getSubject(ITextViewer textViewer, int offset) { 25 | return new Region(offset, 0); 26 | } 27 | 28 | @Override 29 | public String getInformation(ITextViewer textViewer, IRegion subject) { 30 | // not used, since this class also implements IInformationProviderExtension 31 | return String.valueOf(getInformation2(textViewer, subject)); 32 | } 33 | 34 | @Override 35 | public Object getInformation2(ITextViewer textViewer, IRegion subject) { 36 | // subject is currently ignored 37 | try { 38 | String content = textViewer.getDocument().get(); 39 | Reader reader = new StringReader(content); 40 | ParseResult result = AntlrAdapter.convert(reader); 41 | JsonContext syntaxTree = result.getTree(); 42 | 43 | return syntaxTree; 44 | } catch (IOException e) { 45 | JsonLog.logError("Could not compute information", e); 46 | return null; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /jsonedit-editor/src/main/java/com/boothen/jsonedit/editor/JsonNewFileWizard.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.editor; 2 | 3 | import org.eclipse.core.resources.IFile; 4 | import org.eclipse.jface.viewers.IStructuredSelection; 5 | import org.eclipse.ui.IWorkbench; 6 | import org.eclipse.ui.IWorkbenchPage; 7 | import org.eclipse.ui.IWorkbenchWindow; 8 | import org.eclipse.ui.PartInitException; 9 | import org.eclipse.ui.dialogs.WizardNewFileCreationPage; 10 | import org.eclipse.ui.ide.IDE; 11 | import org.eclipse.ui.statushandlers.StatusManager; 12 | import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard; 13 | 14 | /** 15 | * A file wizard for JSON files. 16 | */ 17 | public class JsonNewFileWizard extends BasicNewResourceWizard 18 | { 19 | private WizardNewFileCreationPage mainPage; 20 | 21 | @Override 22 | public void addPages() 23 | { 24 | super.addPages(); 25 | mainPage = new WizardNewFileCreationPage("newFilePage1", getSelection()); 26 | mainPage.setTitle("Create JSON File"); 27 | mainPage.setFileName("file.json"); 28 | addPage(mainPage); 29 | } 30 | 31 | @Override 32 | public void init(IWorkbench workbench, IStructuredSelection currentSelection) 33 | { 34 | super.init(workbench, currentSelection); 35 | setWindowTitle("New JSON File"); 36 | setNeedsProgressMonitor(false); 37 | } 38 | 39 | @Override 40 | public boolean performFinish() 41 | { 42 | IFile file = mainPage.createNewFile(); 43 | if (file == null) { 44 | return false; 45 | } 46 | 47 | selectAndReveal(file); 48 | 49 | final IWorkbenchWindow dw = getWorkbench().getActiveWorkbenchWindow(); 50 | 51 | try { 52 | if (dw != null) { 53 | IWorkbenchPage page = dw.getActivePage(); 54 | 55 | if (page != null) { 56 | IDE.openEditor(page, file, true); 57 | } 58 | } 59 | } 60 | catch (PartInitException e) { 61 | StatusManager.getManager().handle(e.getStatus()); 62 | } 63 | 64 | return true; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /jsonedit-editor/src/main/java/com/boothen/jsonedit/editor/JsonSourceViewer.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.editor; 2 | 3 | import org.eclipse.jface.text.information.IInformationPresenter; 4 | import org.eclipse.jface.text.source.IOverviewRuler; 5 | import org.eclipse.jface.text.source.IVerticalRuler; 6 | import org.eclipse.jface.text.source.SourceViewerConfiguration; 7 | import org.eclipse.jface.text.source.projection.ProjectionViewer; 8 | import org.eclipse.swt.widgets.Composite; 9 | 10 | /** 11 | * A source code viewer for JSON that supports additional operations such as displaying a quick outline info popup. 12 | */ 13 | public class JsonSourceViewer extends ProjectionViewer { 14 | 15 | /** 16 | * Text operation code for requesting the outline for the current input. 17 | */ 18 | public static final int SHOW_OUTLINE = 51; 19 | 20 | private IInformationPresenter fOutlinePresenter; 21 | 22 | /** 23 | * Creates a new JSON projection source viewer. 24 | * 25 | * @param parent the SWT parent control 26 | * @param ruler the vertical ruler 27 | * @param overviewRuler the overview ruler 28 | * @param showAnnotationsOverview true if the overview ruler should be shown 29 | * @param styles the SWT style bits 30 | */ 31 | public JsonSourceViewer(Composite parent, IVerticalRuler ruler, IOverviewRuler overviewRuler, 32 | boolean showAnnotationsOverview, int styles) { 33 | super(parent, ruler, overviewRuler, showAnnotationsOverview, styles); 34 | } 35 | 36 | @Override 37 | public void configure(SourceViewerConfiguration configuration) { 38 | super.configure(configuration); 39 | if (configuration instanceof JsonSourceViewerConfiguration) { 40 | JsonSourceViewerConfiguration jsonConfig = (JsonSourceViewerConfiguration) configuration; 41 | fOutlinePresenter = jsonConfig.getOutlinePresenter(this); 42 | if (fOutlinePresenter != null) { 43 | fOutlinePresenter.install(this); 44 | } 45 | 46 | } 47 | } 48 | 49 | @Override 50 | public void unconfigure() { 51 | if (fOutlinePresenter != null) { 52 | fOutlinePresenter.uninstall(); 53 | fOutlinePresenter = null; 54 | } 55 | super.unconfigure(); 56 | } 57 | 58 | @Override 59 | public boolean canDoOperation(int operation) { 60 | if (operation == SHOW_OUTLINE) { 61 | return fOutlinePresenter != null; 62 | } 63 | 64 | return super.canDoOperation(operation); 65 | } 66 | 67 | @Override 68 | public void doOperation(int operation) { 69 | if (getTextWidget() == null) 70 | return; 71 | 72 | switch (operation) { 73 | case SHOW_OUTLINE: 74 | if (fOutlinePresenter != null) 75 | fOutlinePresenter.showInformation(); 76 | return; 77 | } 78 | 79 | super.doOperation(operation); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /jsonedit-editor/src/main/java/com/boothen/jsonedit/editor/JsonSourceViewerConfiguration.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2014 Boothen Technology Ltd. 3 | * 4 | * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://eclipse.org/org/documents/epl-v10.html 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *******************************************************************************/ 16 | package com.boothen.jsonedit.editor; 17 | 18 | import org.eclipse.jface.preference.IPreferenceStore; 19 | import org.eclipse.jface.text.AbstractInformationControlManager; 20 | import org.eclipse.jface.text.DefaultIndentLineAutoEditStrategy; 21 | import org.eclipse.jface.text.IAutoEditStrategy; 22 | import org.eclipse.jface.text.IDocument; 23 | import org.eclipse.jface.text.IInformationControl; 24 | import org.eclipse.jface.text.IInformationControlCreator; 25 | import org.eclipse.jface.text.formatter.IContentFormatter; 26 | import org.eclipse.jface.text.information.IInformationPresenter; 27 | import org.eclipse.jface.text.information.InformationPresenter; 28 | import org.eclipse.jface.text.presentation.IPresentationReconciler; 29 | import org.eclipse.jface.text.presentation.PresentationReconciler; 30 | import org.eclipse.jface.text.reconciler.IReconciler; 31 | import org.eclipse.jface.text.reconciler.MonoReconciler; 32 | import org.eclipse.jface.text.rules.DefaultDamagerRepairer; 33 | import org.eclipse.jface.text.source.ISourceViewer; 34 | import org.eclipse.swt.widgets.Shell; 35 | import org.eclipse.ui.editors.text.TextSourceViewerConfiguration; 36 | 37 | import com.boothen.jsonedit.antlr.JSONLexer; 38 | import com.boothen.jsonedit.editor.model.JsonReconcilingStrategy; 39 | import com.boothen.jsonedit.model.AntlrTokenScanner; 40 | import com.boothen.jsonedit.model.TokenStyler; 41 | import com.boothen.jsonedit.preferences.JsonTokenStyler; 42 | import com.boothen.jsonedit.preferences.format.JsonContentFormatter; 43 | import com.boothen.jsonedit.quickoutline.QuickOutlinePopup; 44 | 45 | /** 46 | * Configures the text editor. 47 | */ 48 | public class JsonSourceViewerConfiguration extends TextSourceViewerConfiguration { 49 | 50 | private JsonTextEditor textEditor; 51 | 52 | public JsonSourceViewerConfiguration(JsonTextEditor textEditor, IPreferenceStore iPreferenceStore) { 53 | super(iPreferenceStore); 54 | this.textEditor = textEditor; 55 | } 56 | 57 | @Override 58 | public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) { 59 | PresentationReconciler reconciler = new PresentationReconciler(); 60 | 61 | JSONLexer lexer = new JSONLexer(null); 62 | lexer.removeErrorListeners(); // don't print lexer errors to stderr 63 | TokenStyler mapping = new JsonTokenStyler(fPreferenceStore); 64 | AntlrTokenScanner scanner = new AntlrTokenScanner(lexer, mapping); 65 | DefaultDamagerRepairer dr = new DefaultDamagerRepairer(scanner); 66 | reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE); 67 | reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE); 68 | 69 | return reconciler; 70 | } 71 | 72 | @Override 73 | public IContentFormatter getContentFormatter(ISourceViewer sourceViewer) { 74 | IContentFormatter fmt = new JsonContentFormatter(fPreferenceStore); 75 | return fmt; 76 | } 77 | 78 | @Override 79 | public IReconciler getReconciler(ISourceViewer sourceViewer) { 80 | JsonReconcilingStrategy strategy = new JsonReconcilingStrategy(textEditor); 81 | MonoReconciler reconciler = new MonoReconciler(strategy, false); 82 | return reconciler; 83 | } 84 | 85 | @Override 86 | public IAutoEditStrategy[] getAutoEditStrategies(ISourceViewer sourceViewer, String contentType) { 87 | return new IAutoEditStrategy[] { new DefaultIndentLineAutoEditStrategy() }; 88 | } 89 | 90 | /** 91 | * Returns the outline presenter which will determine and shown 92 | * information requested for the current cursor position. 93 | * 94 | * @param sourceViewer the source viewer to be configured by this configuration 95 | * @return an information presenter 96 | */ 97 | public IInformationPresenter getOutlinePresenter(final ISourceViewer sourceViewer) { 98 | IInformationControlCreator controlCreator = new IInformationControlCreator() { 99 | @Override 100 | public IInformationControl createInformationControl(Shell parent) { 101 | return new QuickOutlinePopup(parent, sourceViewer); 102 | } 103 | }; 104 | InformationPresenter presenter = new InformationPresenter(controlCreator); 105 | presenter.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer)); 106 | presenter.setAnchor(AbstractInformationControlManager.ANCHOR_GLOBAL); 107 | presenter.setInformationProvider(new JsonInformationProvider(), IDocument.DEFAULT_CONTENT_TYPE); 108 | presenter.setSizeConstraints(50, 20, true, false); 109 | return presenter; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /jsonedit-editor/src/main/java/com/boothen/jsonedit/editor/Messages.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.editor; 2 | 3 | import java.util.MissingResourceException; 4 | import java.util.ResourceBundle; 5 | 6 | /** 7 | * Provides means to access i18n resources, in particular externalized strings. 8 | */ 9 | public final class Messages { 10 | 11 | /** 12 | * The resource bundle for this plugin 13 | */ 14 | public static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle("i18n/Messages"); 15 | 16 | /** 17 | * Hidden constructor 18 | */ 19 | private Messages() { 20 | //nothing to do here 21 | } 22 | 23 | /** 24 | * Get externalized text string 25 | * @param key the string's ID 26 | * @return the externalized string 27 | */ 28 | public static String getString(String key) { 29 | try { 30 | return RESOURCE_BUNDLE.getString(key); 31 | } catch (MissingResourceException e) { 32 | return '!' + key + '!'; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /jsonedit-editor/src/main/java/com/boothen/jsonedit/editor/RangeHighlighter.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.editor; 2 | 3 | import java.util.Map; 4 | 5 | import org.antlr.v4.runtime.tree.ParseTree; 6 | import org.antlr.v4.runtime.tree.TerminalNode; 7 | import org.eclipse.jface.text.ITextSelection; 8 | import org.eclipse.jface.text.Position; 9 | import org.eclipse.jface.viewers.ISelection; 10 | import org.eclipse.ui.ISelectionListener; 11 | import org.eclipse.ui.IWorkbenchPart; 12 | import org.eclipse.ui.editors.text.TextEditor; 13 | 14 | import com.boothen.jsonedit.model.JsonContextTokenFinder; 15 | import com.boothen.jsonedit.model.ParseTreeInfo; 16 | import com.boothen.jsonedit.model.Segment; 17 | 18 | /** 19 | * Updates the text editors highlight range (bluish line left of the vertical ruler) 20 | * according to the current text selection. 21 | */ 22 | public class RangeHighlighter implements ISelectionListener { 23 | 24 | private TextEditor textEditor; 25 | private ParseTree jsonContext; 26 | private Map positions; 27 | 28 | /** 29 | * @param textEditor the text editor to use 30 | */ 31 | public RangeHighlighter(TextEditor textEditor) { 32 | this.textEditor = textEditor; 33 | } 34 | 35 | @Override 36 | public void selectionChanged(IWorkbenchPart part, ISelection selection) { 37 | if (jsonContext == null) { 38 | return; 39 | } 40 | 41 | if (selection instanceof ITextSelection) { 42 | ITextSelection textSelection = (ITextSelection) selection; 43 | int start = textSelection.getOffset(); 44 | int length = textSelection.getLength(); 45 | ParseTree element = jsonContext.accept(new JsonContextTokenFinder(start, start + length, positions)); 46 | // TODO: consider using the same rules as the FoldingVisitor 47 | if (element instanceof TerminalNode) { 48 | element = element.getParent(); 49 | } 50 | if (element != null) { 51 | Segment seg = ParseTreeInfo.getSegment(element); 52 | textEditor.setHighlightRange(seg.getStart(), seg.getLength(), false); 53 | } else { 54 | textEditor.resetHighlightRange(); 55 | } 56 | } 57 | } 58 | 59 | /** 60 | * @param tree the syntax tree 61 | * @param positions maps tree elements to document positions 62 | */ 63 | public void setInput(ParseTree tree, Map positions) { 64 | this.jsonContext = tree; 65 | this.positions = positions; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /jsonedit-editor/src/main/java/com/boothen/jsonedit/editor/model/JsonReconcilingStrategy.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2014 Boothen Technology Ltd. 3 | * 4 | * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://eclipse.org/org/documents/epl-v10.html 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *******************************************************************************/ 16 | package com.boothen.jsonedit.editor.model; 17 | 18 | import java.io.IOException; 19 | import java.io.Reader; 20 | import java.io.StringReader; 21 | import java.util.ArrayList; 22 | import java.util.Collection; 23 | import java.util.LinkedHashMap; 24 | import java.util.List; 25 | import java.util.Map; 26 | 27 | import org.antlr.v4.runtime.tree.ParseTree; 28 | import org.eclipse.core.runtime.IProgressMonitor; 29 | import org.eclipse.core.runtime.IStatus; 30 | import org.eclipse.core.runtime.Status; 31 | import org.eclipse.jface.text.IDocument; 32 | import org.eclipse.jface.text.IRegion; 33 | import org.eclipse.jface.text.Position; 34 | import org.eclipse.jface.text.reconciler.DirtyRegion; 35 | import org.eclipse.jface.text.reconciler.IReconcilingStrategy; 36 | import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension; 37 | import org.eclipse.swt.widgets.Display; 38 | import org.eclipse.ui.statushandlers.StatusManager; 39 | 40 | import com.boothen.jsonedit.antlr.JSONParser.JsonContext; 41 | import com.boothen.jsonedit.editor.Activator; 42 | import com.boothen.jsonedit.editor.JsonTextEditor; 43 | import com.boothen.jsonedit.folding.JsonFoldingPositionsBuilder; 44 | import com.boothen.jsonedit.model.AntlrAdapter; 45 | import com.boothen.jsonedit.model.ParseProblem; 46 | import com.boothen.jsonedit.model.ParseResult; 47 | import com.boothen.jsonedit.problems.DuplicateKeyFinder; 48 | import com.boothen.jsonedit.problems.StringProblemFinder; 49 | import com.boothen.jsonedit.text.PositionVisitor; 50 | 51 | /** 52 | * Re-compute the JSON syntax tree and update the JSON text editor based on the results. 53 | * This includes folding structure, markers and the syntax error list. 54 | */ 55 | public class JsonReconcilingStrategy implements IReconcilingStrategy, IReconcilingStrategyExtension { 56 | 57 | private JsonTextEditor textEditor; 58 | 59 | private IDocument fDocument; 60 | 61 | private IProgressMonitor monitor; 62 | 63 | private JsonFoldingPositionsBuilder foldingPositionsBuilder = new JsonFoldingPositionsBuilder(); 64 | 65 | private ParseTreeComparator treeComparator = new ParseTreeComparator(); 66 | 67 | /** 68 | * @param textEditor the JSON text editor to work on 69 | */ 70 | public JsonReconcilingStrategy(JsonTextEditor textEditor) { 71 | this.textEditor = textEditor; 72 | } 73 | 74 | @Override 75 | public void setDocument(IDocument document) { 76 | this.fDocument = document; 77 | } 78 | 79 | @Override 80 | public void setProgressMonitor(IProgressMonitor monitor) { 81 | this.monitor = monitor; 82 | } 83 | 84 | @Override 85 | public void initialReconcile() { 86 | reconcileSafely(0, fDocument.getLength()); 87 | } 88 | 89 | @Override 90 | public void reconcile(IRegion partition) { 91 | reconcileSafely(partition.getOffset(), partition.getLength()); 92 | } 93 | 94 | @Override 95 | public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) { 96 | reconcileSafely(subRegion.getOffset(), subRegion.getLength()); 97 | } 98 | 99 | private void reconcileSafely(int offset, int length) { 100 | try { 101 | monitor.beginTask("Updating syntax tree", IProgressMonitor.UNKNOWN); 102 | reconcile(offset, length); 103 | } catch (Exception e) { 104 | String message = e.toString(); 105 | Status status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, message, e); 106 | StatusManager.getManager().handle(status); 107 | } finally { 108 | monitor.done(); 109 | } 110 | } 111 | 112 | private void reconcile(int offset, int length) throws IOException { 113 | Reader reader = new StringReader(fDocument.get()); 114 | final ParseResult result = AntlrAdapter.convert(reader); 115 | final JsonContext syntaxTree = result.getTree(); 116 | final List problems = new ArrayList<>(); 117 | problems.addAll(result.getLexerErrors()); 118 | problems.addAll(result.getParserErrors()); 119 | 120 | final LinkedHashMap positions = syntaxTree.accept(new PositionVisitor()); 121 | 122 | problems.addAll(addCustomProblems(syntaxTree)); 123 | 124 | final Map oldToNew = treeComparator.update(syntaxTree, positions); 125 | 126 | final List foldPositions = foldingPositionsBuilder.getFoldingPositions(syntaxTree); 127 | 128 | if (textEditor != null) { 129 | Display.getDefault().asyncExec(new Runnable() { 130 | @Override 131 | public void run() { 132 | textEditor.updateDocumentPositions(positions.values()); 133 | textEditor.updateFoldingStructure(foldPositions); 134 | textEditor.updateSyntaxTree(syntaxTree, oldToNew, positions); 135 | textEditor.updateProblemMarkers(problems); 136 | } 137 | }); 138 | } 139 | } 140 | 141 | private Collection addCustomProblems(JsonContext syntaxTree) { 142 | Collection problems = new ArrayList<>(); 143 | 144 | // add duplicate keys 145 | syntaxTree.accept(new DuplicateKeyFinder(problems)); 146 | 147 | // add unneeded escaping warnings 148 | syntaxTree.accept(new StringProblemFinder(problems)); 149 | 150 | return problems; 151 | } 152 | 153 | } 154 | -------------------------------------------------------------------------------- /jsonedit-editor/src/main/java/com/boothen/jsonedit/editor/model/ParseTreeComparator.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.editor.model; 2 | 3 | import java.util.Collections; 4 | import java.util.Iterator; 5 | import java.util.LinkedHashMap; 6 | import java.util.Map; 7 | import java.util.Map.Entry; 8 | 9 | import org.antlr.v4.runtime.tree.ParseTree; 10 | import org.eclipse.jface.text.Position; 11 | 12 | import com.boothen.jsonedit.antlr.JSONParser.JsonContext; 13 | 14 | /** 15 | * Compares two parse trees. 16 | */ 17 | public class ParseTreeComparator { 18 | 19 | private JsonContext oldRoot; 20 | private Map oldPositions = Collections.emptyMap(); 21 | 22 | /** 23 | * Requires the positions map to by ordered as they are found in the tree. 24 | * An alternative implementation could iterate over the new syntrax tree to avoid that. 25 | * @param syntaxTree the syntax tree 26 | * @param positions an ordered map. 27 | * @return a mapping from old to new tree elements 28 | */ 29 | public Map update(JsonContext syntaxTree, LinkedHashMap positions) { 30 | 31 | Map oldToNew = new LinkedHashMap<>(); 32 | if (oldRoot != null) { 33 | compareTrees(positions, oldPositions, oldToNew); 34 | } 35 | 36 | oldRoot = syntaxTree; 37 | oldPositions = positions; 38 | 39 | return oldToNew; 40 | } 41 | 42 | 43 | private void compareTrees(LinkedHashMap newPositions, 44 | Map oldPositions, Map oldToNew) { 45 | 46 | Map copyNew = new LinkedHashMap<>(newPositions); 47 | Map copyOld = new LinkedHashMap<>(oldPositions); 48 | 49 | // matching elements are removed from the corresponding map to avoid that 50 | // an element is matched twice. 51 | // Attention must be paid to ValueContext instances, since they have identical segment bounds 52 | // as their only child. 53 | Iterator> itNew = copyNew.entrySet().iterator(); 54 | while (itNew.hasNext()) { 55 | Entry entryNew = itNew.next(); 56 | 57 | Iterator> itOld = copyOld.entrySet().iterator(); 58 | while (itOld.hasNext()) { 59 | Entry entryOld = itOld.next(); 60 | if (samePosition(entryNew.getValue(), entryOld.getValue())) { 61 | oldToNew.put(entryOld.getKey(), entryNew.getKey()); 62 | itOld.remove(); 63 | itNew.remove(); 64 | break; 65 | } 66 | } 67 | } 68 | } 69 | 70 | private static boolean samePosition(Position a, Position b) { 71 | return a.getOffset() + a.getLength() == b.getOffset() + b.getLength(); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /jsonedit-feature/build.properties: -------------------------------------------------------------------------------- 1 | bin.includes = feature.xml 2 | -------------------------------------------------------------------------------- /jsonedit-feature/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | com.boothen 9 | jsonedit-parent 10 | 1.1.3 11 | 12 | 13 | jsonedit-feature 14 | eclipse-feature 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.m2e 21 | lifecycle-mapping 22 | 1.0.0 23 | 24 | 25 | 26 | 27 | 28 | 29 | org.eclipse.tycho 30 | 31 | 32 | tycho-packaging-plugin 33 | 34 | 35 | [0.18.0,) 36 | 37 | 38 | 39 | build-qualifier-aggregator 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /jsonedit-folding/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Bundle-ManifestVersion: 2 3 | Bundle-Name: JSON Editor Folding 4 | Bundle-SymbolicName: jsonedit-folding 5 | Bundle-Version: 1.1.3 6 | Bundle-RequiredExecutionEnvironment: JavaSE-1.7 7 | Bundle-Vendor: Boothen Technology 8 | Require-Bundle: org.eclipse.jface.text, 9 | jsonedit-model, 10 | org.antlr.antlr4-runtime 11 | Export-Package: com.boothen.jsonedit.folding 12 | -------------------------------------------------------------------------------- /jsonedit-folding/build.properties: -------------------------------------------------------------------------------- 1 | source.. = src/main/java 2 | output.. = target/classes 3 | bin.includes = META-INF/,\ 4 | . 5 | -------------------------------------------------------------------------------- /jsonedit-folding/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | 7 | com.boothen 8 | jsonedit-parent 9 | 1.1.3 10 | 11 | 12 | jsonedit-folding 13 | eclipse-plugin 14 | 15 | 16 | -------------------------------------------------------------------------------- /jsonedit-folding/src/main/java/com/boothen/jsonedit/folding/FoldingVisitor.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.folding; 2 | 3 | import java.util.List; 4 | 5 | import org.antlr.v4.runtime.ParserRuleContext; 6 | import org.eclipse.jface.text.Position; 7 | 8 | import com.boothen.jsonedit.antlr.JSONBaseVisitor; 9 | import com.boothen.jsonedit.antlr.JSONParser.ArrayContext; 10 | import com.boothen.jsonedit.antlr.JSONParser.ObjectContext; 11 | 12 | /** 13 | * Creates {@link Position} instances that wrap around inner nodes in the syntax tree. 14 | * The root element is excluded explicitly. 15 | */ 16 | class FoldingVisitor extends JSONBaseVisitor { 17 | 18 | private final List positions; 19 | 20 | /** 21 | * @param positions an (empty) list that will be filled during tree traversal 22 | */ 23 | public FoldingVisitor(List positions) { 24 | this.positions = positions; 25 | } 26 | 27 | @Override 28 | public Void visitObject(ObjectContext ctx) { 29 | if (isFoldingPoint(ctx)) { 30 | positions.add(createPosition(ctx)); 31 | } 32 | return super.visitObject(ctx); 33 | } 34 | 35 | @Override 36 | public Void visitArray(ArrayContext ctx) { 37 | if (isFoldingPoint(ctx)) { 38 | positions.add(createPosition(ctx)); 39 | } 40 | return super.visitArray(ctx); 41 | } 42 | 43 | private Position createPosition(ParserRuleContext ctx) { 44 | int startIndex = ctx.start.getStartIndex(); 45 | int stopIndex = ctx.stop.getStopIndex(); 46 | Position pos = new Position(startIndex, stopIndex - startIndex); 47 | return pos; 48 | } 49 | 50 | private boolean isFoldingPoint(ParserRuleContext ctx) { 51 | if (ctx.exception != null) { 52 | return false; 53 | } 54 | 55 | // the root element is at depth 1 and not part of the traversal 56 | // it contains one child with identical start/stop tokens 57 | // we filter it out to avoid folding the entire file 58 | if (ctx.depth() <= 2) { 59 | return false; 60 | } 61 | 62 | // Skip elements that span less than two lines 63 | return ctx.start.getLine() < ctx.stop.getLine() - 1; 64 | } 65 | } 66 | 67 | -------------------------------------------------------------------------------- /jsonedit-folding/src/main/java/com/boothen/jsonedit/folding/JsonFoldingPositionsBuilder.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2014 Boothen Technology Ltd. 3 | * 4 | * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://eclipse.org/org/documents/epl-v10.html 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *******************************************************************************/ 16 | package com.boothen.jsonedit.folding; 17 | 18 | import java.util.LinkedList; 19 | import java.util.List; 20 | 21 | import org.eclipse.jface.text.Position; 22 | 23 | import com.boothen.jsonedit.antlr.JSONParser.JsonContext; 24 | 25 | public class JsonFoldingPositionsBuilder { 26 | 27 | public List getFoldingPositions(JsonContext jsonContext) { 28 | List positions = new LinkedList(); 29 | jsonContext.accept(new FoldingVisitor(positions)); 30 | return positions; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /jsonedit-model/.gitignore: -------------------------------------------------------------------------------- 1 | grammar/antlr*.jar 2 | grammar/json-grammar/ -------------------------------------------------------------------------------- /jsonedit-model/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Bundle-ManifestVersion: 2 3 | Bundle-Name: JSON Editor Model Generator 4 | Bundle-SymbolicName: jsonedit-model 5 | Bundle-Version: 1.1.3 6 | Bundle-RequiredExecutionEnvironment: JavaSE-1.7 7 | Bundle-Vendor: Boothen Technology 8 | Require-Bundle: org.eclipse.jface.text, 9 | org.antlr.antlr4-runtime, 10 | jsonedit-core, 11 | org.eclipse.swt, 12 | org.eclipse.core.resources 13 | Export-Package: com.boothen.jsonedit.antlr, 14 | com.boothen.jsonedit.model, 15 | com.boothen.jsonedit.problems 16 | -------------------------------------------------------------------------------- /jsonedit-model/build.properties: -------------------------------------------------------------------------------- 1 | source.. = src/main/java 2 | output.. = target/classes 3 | bin.includes = META-INF/,\ 4 | . 5 | -------------------------------------------------------------------------------- /jsonedit-model/grammar/JSON.g4: -------------------------------------------------------------------------------- 1 | 2 | /** Taken from "The Definitive ANTLR 4 Reference" by Terence Parr */ 3 | 4 | // Derived from http://json.org 5 | parser grammar JSON; 6 | 7 | options { tokenVocab=JSONLexer; } 8 | 9 | json 10 | : value 11 | ; 12 | 13 | object 14 | : '{' pair (',' pair)* '}' 15 | | '{' '}' 16 | ; 17 | 18 | pair 19 | : STRING ':' value 20 | ; 21 | 22 | array 23 | : '[' value (',' value)* ']' 24 | | '[' ']' 25 | ; 26 | 27 | value 28 | : STRING 29 | | NUMBER 30 | | object 31 | | array 32 | | 'true' 33 | | 'false' 34 | | 'null' 35 | ; 36 | -------------------------------------------------------------------------------- /jsonedit-model/grammar/JSONLexer.g4: -------------------------------------------------------------------------------- 1 | 2 | /** Taken from "The Definitive ANTLR 4 Reference" by Terence Parr */ 3 | 4 | // Derived from http://json.org 5 | lexer grammar JSONLexer; 6 | 7 | channels { 8 | COMMENTS_CHANNEL 9 | } 10 | 11 | 12 | STRING 13 | : '"' (ESC | SAFECODEPOINT)* '"' 14 | ; 15 | 16 | 17 | fragment ESC 18 | : '\\' (["\\/bfnrt] | UNICODE | SAFECODEPOINT ) 19 | ; 20 | 21 | 22 | fragment UNICODE 23 | : 'u' HEX HEX HEX HEX 24 | ; 25 | 26 | 27 | fragment HEX 28 | : [0-9a-fA-F] 29 | ; 30 | 31 | 32 | fragment SAFECODEPOINT 33 | : ~ ["\\\u0000-\u001F] 34 | ; 35 | 36 | 37 | NUMBER 38 | : '-'? INT ('.' [0-9] +)? EXP? 39 | ; 40 | 41 | // keywords 42 | 43 | TRUE : 'true'; 44 | FALSE : 'false'; 45 | NULL : 'null'; 46 | 47 | // more constants 48 | 49 | BEGIN_ARRAY : '['; 50 | END_ARRAY : ']'; 51 | BEGIN_OBJECT : '{'; 52 | END_OBJECT : '}'; 53 | COMMA : ','; 54 | COLON : ':'; 55 | 56 | fragment INT 57 | : '0' | [1-9] [0-9]* 58 | ; 59 | 60 | // no leading zeros 61 | 62 | fragment EXP 63 | : [Ee] [+\-]? INT 64 | ; 65 | 66 | // \- since - means "range" inside [...] 67 | 68 | WS 69 | : [ \t\n\r] + -> channel(HIDDEN) 70 | ; 71 | 72 | LINE_COMMENT 73 | : '//' ~[\r\n]* -> channel(COMMENTS_CHANNEL) 74 | ; 75 | 76 | BLOCK_COMMENT 77 | : '/*' .*? '*/' -> channel(COMMENTS_CHANNEL) 78 | ; 79 | 80 | UNKNOWN 81 | : ~ [{}[\],:"0-9\- \t\r\n]+ 82 | ; 83 | 84 | // collect everything else and put it into a single token to aggregate consecutive error chars. 85 | -------------------------------------------------------------------------------- /jsonedit-model/grammar/create_code.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ANTLR_VERSION=4.7.1 4 | FILENAME="antlr-$ANTLR_VERSION-complete.jar" 5 | 6 | if ! [ -f $FILENAME ]; then 7 | URL="http://www.antlr.org/download/$FILENAME" 8 | echo "Downloading $URL" 9 | curl -o $FILENAME $URL 10 | else 11 | echo "File $FILENAME already exists" 12 | fi 13 | 14 | echo "Compiling grammar file" 15 | java -jar ${FILENAME} JSONLexer.g4 JSON.g4 -visitor -package com.boothen.jsonedit.antlr -o json-grammar 16 | echo "Compilation done!" 17 | 18 | echo "Replacing tabs with spaces" 19 | find json-grammar/*.java -exec sed -i 's/\t/ /g' {} + 20 | 21 | echo "Adding a new-line char at the end (if missing)" 22 | find json-grammar/*.java -exec sed -i -e '$a\' {} + 23 | 24 | echo "Moving generated Java files" 25 | mv -v json-grammar/*.java ../src/main/java/com/boothen/jsonedit/antlr/ 26 | -------------------------------------------------------------------------------- /jsonedit-model/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | 7 | com.boothen 8 | jsonedit-parent 9 | 1.1.3 10 | 11 | 12 | jsonedit-model 13 | eclipse-plugin 14 | 15 | 16 | -------------------------------------------------------------------------------- /jsonedit-model/src/main/java/com/boothen/jsonedit/antlr/JSONBaseListener.java: -------------------------------------------------------------------------------- 1 | // Generated from JSON.g4 by ANTLR 4.7.1 2 | package com.boothen.jsonedit.antlr; 3 | 4 | import org.antlr.v4.runtime.ParserRuleContext; 5 | import org.antlr.v4.runtime.tree.ErrorNode; 6 | import org.antlr.v4.runtime.tree.TerminalNode; 7 | 8 | /** 9 | * This class provides an empty implementation of {@link JSONListener}, 10 | * which can be extended to create a listener which only needs to handle a subset 11 | * of the available methods. 12 | */ 13 | public class JSONBaseListener implements JSONListener { 14 | /** 15 | * {@inheritDoc} 16 | * 17 | *

The default implementation does nothing.

18 | */ 19 | @Override public void enterJson(JSONParser.JsonContext ctx) { /* empty */ } 20 | /** 21 | * {@inheritDoc} 22 | * 23 | *

The default implementation does nothing.

24 | */ 25 | @Override public void exitJson(JSONParser.JsonContext ctx) { /* empty */ } 26 | /** 27 | * {@inheritDoc} 28 | * 29 | *

The default implementation does nothing.

30 | */ 31 | @Override public void enterObject(JSONParser.ObjectContext ctx) { /* empty */ } 32 | /** 33 | * {@inheritDoc} 34 | * 35 | *

The default implementation does nothing.

36 | */ 37 | @Override public void exitObject(JSONParser.ObjectContext ctx) { /* empty */ } 38 | /** 39 | * {@inheritDoc} 40 | * 41 | *

The default implementation does nothing.

42 | */ 43 | @Override public void enterPair(JSONParser.PairContext ctx) { /* empty */ } 44 | /** 45 | * {@inheritDoc} 46 | * 47 | *

The default implementation does nothing.

48 | */ 49 | @Override public void exitPair(JSONParser.PairContext ctx) { /* empty */ } 50 | /** 51 | * {@inheritDoc} 52 | * 53 | *

The default implementation does nothing.

54 | */ 55 | @Override public void enterArray(JSONParser.ArrayContext ctx) { /* empty */ } 56 | /** 57 | * {@inheritDoc} 58 | * 59 | *

The default implementation does nothing.

60 | */ 61 | @Override public void exitArray(JSONParser.ArrayContext ctx) { /* empty */ } 62 | /** 63 | * {@inheritDoc} 64 | * 65 | *

The default implementation does nothing.

66 | */ 67 | @Override public void enterValue(JSONParser.ValueContext ctx) { /* empty */ } 68 | /** 69 | * {@inheritDoc} 70 | * 71 | *

The default implementation does nothing.

72 | */ 73 | @Override public void exitValue(JSONParser.ValueContext ctx) { /* empty */ } 74 | 75 | /** 76 | * {@inheritDoc} 77 | * 78 | *

The default implementation does nothing.

79 | */ 80 | @Override public void enterEveryRule(ParserRuleContext ctx) { /* empty */ } 81 | /** 82 | * {@inheritDoc} 83 | * 84 | *

The default implementation does nothing.

85 | */ 86 | @Override public void exitEveryRule(ParserRuleContext ctx) { /* empty */ } 87 | /** 88 | * {@inheritDoc} 89 | * 90 | *

The default implementation does nothing.

91 | */ 92 | @Override public void visitTerminal(TerminalNode node) { /* empty */ } 93 | /** 94 | * {@inheritDoc} 95 | * 96 | *

The default implementation does nothing.

97 | */ 98 | @Override public void visitErrorNode(ErrorNode node) { /* empty */ } 99 | } 100 | -------------------------------------------------------------------------------- /jsonedit-model/src/main/java/com/boothen/jsonedit/antlr/JSONBaseVisitor.java: -------------------------------------------------------------------------------- 1 | // Generated from JSON.g4 by ANTLR 4.7.1 2 | package com.boothen.jsonedit.antlr; 3 | import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; 4 | 5 | /** 6 | * This class provides an empty implementation of {@link JSONVisitor}, 7 | * which can be extended to create a visitor which only needs to handle a subset 8 | * of the available methods. 9 | * 10 | * @param The return type of the visit operation. Use {@link Void} for 11 | * operations with no return type. 12 | */ 13 | public class JSONBaseVisitor extends AbstractParseTreeVisitor implements JSONVisitor { 14 | /** 15 | * {@inheritDoc} 16 | * 17 | *

The default implementation returns the result of calling 18 | * {@link #visitChildren} on {@code ctx}.

19 | */ 20 | @Override public T visitJson(JSONParser.JsonContext ctx) { return visitChildren(ctx); } 21 | /** 22 | * {@inheritDoc} 23 | * 24 | *

The default implementation returns the result of calling 25 | * {@link #visitChildren} on {@code ctx}.

26 | */ 27 | @Override public T visitObject(JSONParser.ObjectContext ctx) { return visitChildren(ctx); } 28 | /** 29 | * {@inheritDoc} 30 | * 31 | *

The default implementation returns the result of calling 32 | * {@link #visitChildren} on {@code ctx}.

33 | */ 34 | @Override public T visitPair(JSONParser.PairContext ctx) { return visitChildren(ctx); } 35 | /** 36 | * {@inheritDoc} 37 | * 38 | *

The default implementation returns the result of calling 39 | * {@link #visitChildren} on {@code ctx}.

40 | */ 41 | @Override public T visitArray(JSONParser.ArrayContext ctx) { return visitChildren(ctx); } 42 | /** 43 | * {@inheritDoc} 44 | * 45 | *

The default implementation returns the result of calling 46 | * {@link #visitChildren} on {@code ctx}.

47 | */ 48 | @Override public T visitValue(JSONParser.ValueContext ctx) { return visitChildren(ctx); } 49 | } 50 | -------------------------------------------------------------------------------- /jsonedit-model/src/main/java/com/boothen/jsonedit/antlr/JSONListener.java: -------------------------------------------------------------------------------- 1 | // Generated from JSON.g4 by ANTLR 4.7.1 2 | package com.boothen.jsonedit.antlr; 3 | import org.antlr.v4.runtime.tree.ParseTreeListener; 4 | 5 | /** 6 | * This interface defines a complete listener for a parse tree produced by 7 | * {@link JSONParser}. 8 | */ 9 | public interface JSONListener extends ParseTreeListener { 10 | /** 11 | * Enter a parse tree produced by {@link JSONParser#json}. 12 | * @param ctx the parse tree 13 | */ 14 | void enterJson(JSONParser.JsonContext ctx); 15 | /** 16 | * Exit a parse tree produced by {@link JSONParser#json}. 17 | * @param ctx the parse tree 18 | */ 19 | void exitJson(JSONParser.JsonContext ctx); 20 | /** 21 | * Enter a parse tree produced by {@link JSONParser#object}. 22 | * @param ctx the parse tree 23 | */ 24 | void enterObject(JSONParser.ObjectContext ctx); 25 | /** 26 | * Exit a parse tree produced by {@link JSONParser#object}. 27 | * @param ctx the parse tree 28 | */ 29 | void exitObject(JSONParser.ObjectContext ctx); 30 | /** 31 | * Enter a parse tree produced by {@link JSONParser#pair}. 32 | * @param ctx the parse tree 33 | */ 34 | void enterPair(JSONParser.PairContext ctx); 35 | /** 36 | * Exit a parse tree produced by {@link JSONParser#pair}. 37 | * @param ctx the parse tree 38 | */ 39 | void exitPair(JSONParser.PairContext ctx); 40 | /** 41 | * Enter a parse tree produced by {@link JSONParser#array}. 42 | * @param ctx the parse tree 43 | */ 44 | void enterArray(JSONParser.ArrayContext ctx); 45 | /** 46 | * Exit a parse tree produced by {@link JSONParser#array}. 47 | * @param ctx the parse tree 48 | */ 49 | void exitArray(JSONParser.ArrayContext ctx); 50 | /** 51 | * Enter a parse tree produced by {@link JSONParser#value}. 52 | * @param ctx the parse tree 53 | */ 54 | void enterValue(JSONParser.ValueContext ctx); 55 | /** 56 | * Exit a parse tree produced by {@link JSONParser#value}. 57 | * @param ctx the parse tree 58 | */ 59 | void exitValue(JSONParser.ValueContext ctx); 60 | } 61 | -------------------------------------------------------------------------------- /jsonedit-model/src/main/java/com/boothen/jsonedit/antlr/JSONVisitor.java: -------------------------------------------------------------------------------- 1 | // Generated from JSON.g4 by ANTLR 4.7.1 2 | package com.boothen.jsonedit.antlr; 3 | import org.antlr.v4.runtime.tree.ParseTreeVisitor; 4 | 5 | /** 6 | * This interface defines a complete generic visitor for a parse tree produced 7 | * by {@link JSONParser}. 8 | * 9 | * @param The return type of the visit operation. Use {@link Void} for 10 | * operations with no return type. 11 | */ 12 | public interface JSONVisitor extends ParseTreeVisitor { 13 | /** 14 | * Visit a parse tree produced by {@link JSONParser#json}. 15 | * @param ctx the parse tree 16 | * @return the visitor result 17 | */ 18 | T visitJson(JSONParser.JsonContext ctx); 19 | /** 20 | * Visit a parse tree produced by {@link JSONParser#object}. 21 | * @param ctx the parse tree 22 | * @return the visitor result 23 | */ 24 | T visitObject(JSONParser.ObjectContext ctx); 25 | /** 26 | * Visit a parse tree produced by {@link JSONParser#pair}. 27 | * @param ctx the parse tree 28 | * @return the visitor result 29 | */ 30 | T visitPair(JSONParser.PairContext ctx); 31 | /** 32 | * Visit a parse tree produced by {@link JSONParser#array}. 33 | * @param ctx the parse tree 34 | * @return the visitor result 35 | */ 36 | T visitArray(JSONParser.ArrayContext ctx); 37 | /** 38 | * Visit a parse tree produced by {@link JSONParser#value}. 39 | * @param ctx the parse tree 40 | * @return the visitor result 41 | */ 42 | T visitValue(JSONParser.ValueContext ctx); 43 | } 44 | -------------------------------------------------------------------------------- /jsonedit-model/src/main/java/com/boothen/jsonedit/model/AntlrAdapter.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.model; 2 | 3 | import java.io.IOException; 4 | import java.io.Reader; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | import org.antlr.v4.runtime.ANTLRInputStream; 9 | import org.antlr.v4.runtime.BaseErrorListener; 10 | import org.antlr.v4.runtime.CharStream; 11 | import org.antlr.v4.runtime.CommonTokenStream; 12 | import org.antlr.v4.runtime.RecognitionException; 13 | import org.antlr.v4.runtime.Recognizer; 14 | import org.antlr.v4.runtime.Token; 15 | 16 | import com.boothen.jsonedit.antlr.JSONLexer; 17 | import com.boothen.jsonedit.antlr.JSONParser; 18 | import com.boothen.jsonedit.antlr.JSONParser.JsonContext; 19 | import com.boothen.jsonedit.model.ParseProblem.Severity; 20 | 21 | /** 22 | * 23 | */ 24 | public class AntlrAdapter { 25 | 26 | /** 27 | * @param reader the reader that provides the document 28 | * @return the result of the parsing operation 29 | * @throws IOException if the document cannot be read - parsing errors are in ParseResult 30 | */ 31 | public static ParseResult convert(Reader reader) throws IOException { 32 | CharStream stream = new ANTLRInputStream(reader); 33 | 34 | JSONLexer lexer = new JSONLexer(stream); 35 | LexerErrorListener lexerErrorListener = new LexerErrorListener(); 36 | lexer.removeErrorListeners(); 37 | lexer.addErrorListener(lexerErrorListener); 38 | 39 | JSONParser parser = new JSONParser(new CommonTokenStream(lexer)); 40 | ParserErrorListener parserErrorListener = new ParserErrorListener(); 41 | parser.removeErrorListeners(); 42 | parser.addErrorListener(parserErrorListener); 43 | 44 | JsonContext syntaxTree = parser.json(); 45 | List lexerErrors = lexerErrorListener.getErrors(); 46 | List parserErrors = parserErrorListener.getErrors(); 47 | ParseResult result = new ParseResult(syntaxTree, lexerErrors, parserErrors); 48 | return result; 49 | } 50 | 51 | private static class LexerErrorListener extends BaseErrorListener { 52 | private final List errorList = new ArrayList<>(); 53 | 54 | public LexerErrorListener() { 55 | // public 56 | } 57 | 58 | @Override 59 | public void syntaxError(Recognizer recognizer, Object offendingSymbol, int line, int posInLine, 60 | String msg, RecognitionException e) { 61 | Token offendingToken = e != null ? e.getOffendingToken() : null; 62 | int endPos; 63 | if (offendingToken != null) { 64 | endPos = posInLine + offendingToken.getText().length(); 65 | } else { 66 | endPos = posInLine + 1; 67 | } 68 | ParseProblem error = new ParseProblem(Severity.ERROR, msg, line, posInLine, endPos); 69 | errorList.add(error); 70 | } 71 | 72 | /** 73 | * @return the errorList 74 | */ 75 | public List getErrors() { 76 | return errorList; 77 | } 78 | } 79 | 80 | private static class ParserErrorListener extends BaseErrorListener { 81 | private final List errorList = new ArrayList<>(); 82 | 83 | public ParserErrorListener() { 84 | // public 85 | } 86 | 87 | @Override 88 | public void syntaxError(Recognizer recognizer, Object offendingSymbol, int line, int posInLine, 89 | String msg, RecognitionException e) { 90 | Token offendingToken = null; 91 | if (e != null) { 92 | offendingToken = e.getOffendingToken(); 93 | } 94 | if (offendingSymbol instanceof Token) { 95 | offendingToken = (Token) offendingSymbol; 96 | } 97 | 98 | int endPos; 99 | if (offendingToken != null) { 100 | endPos = posInLine + offendingToken.getText().length(); 101 | } else { 102 | endPos = posInLine + 1; 103 | } 104 | 105 | ParseProblem error = new ParseProblem(Severity.ERROR, msg, line, posInLine, endPos); 106 | errorList.add(error); 107 | } 108 | 109 | /** 110 | * @return the errorList 111 | */ 112 | public List getErrors() { 113 | return errorList; 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /jsonedit-model/src/main/java/com/boothen/jsonedit/model/AntlrTokenScanner.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.model; 2 | 3 | import org.antlr.v4.runtime.ANTLRInputStream; 4 | import org.antlr.v4.runtime.CommonToken; 5 | import org.antlr.v4.runtime.Lexer; 6 | import org.antlr.v4.runtime.Token; 7 | import org.eclipse.jface.text.BadLocationException; 8 | import org.eclipse.jface.text.IDocument; 9 | import org.eclipse.jface.text.TextAttribute; 10 | import org.eclipse.jface.text.rules.IToken; 11 | import org.eclipse.jface.text.rules.ITokenScanner; 12 | 13 | import com.boothen.jsonedit.antlr.JSONLexer; 14 | import com.boothen.jsonedit.core.JsonLog; 15 | import com.boothen.jsonedit.core.preferences.TokenStyle; 16 | 17 | /** 18 | * Use the ANTLR lexer to extract JSON tokens from a document. 19 | * It uses a 2-step lookahead to identify KEY text strings. It therefore does not require to 20 | * construct a syntax tree. 21 | */ 22 | public class AntlrTokenScanner implements ITokenScanner { 23 | 24 | private int offset; 25 | private Lexer lexer; 26 | private CommonToken current; 27 | private CommonToken next; 28 | private CommonToken afterNext; 29 | private TokenStyler tokenStyler; 30 | 31 | /** 32 | * Uses the given JSONLexer 33 | * @param lexer the lexer to use 34 | */ 35 | public AntlrTokenScanner(Lexer lexer) { 36 | this.lexer = lexer; 37 | this.tokenStyler = new TokenStyler() { 38 | @Override 39 | public TextAttribute apply(TokenStyle style) { 40 | return new TextAttribute(null); 41 | } 42 | }; 43 | } 44 | 45 | /** 46 | * @param lexer the lexer to use 47 | * @param mapping the mapping from token type to result 48 | */ 49 | public AntlrTokenScanner(Lexer lexer, TokenStyler mapping) { 50 | this.lexer = lexer; 51 | this.tokenStyler = mapping; 52 | } 53 | 54 | @Override 55 | public void setRange(IDocument document, int offset, int length) { 56 | this.offset = offset; 57 | try { 58 | String text = document.get(offset, length); 59 | lexer.setInputStream(new ANTLRInputStream(text)); 60 | next = (CommonToken) lexer.nextToken(); 61 | afterNext = (CommonToken) lexer.nextToken(); 62 | } catch (BadLocationException e) { 63 | JsonLog.logError("Attempting to access a non-existing position", e); 64 | } 65 | } 66 | 67 | @Override 68 | public IToken nextToken() { 69 | Token token = lexer.nextToken(); 70 | 71 | if (!(token instanceof CommonToken)) { 72 | // this doesn't seem to happen in practice 73 | // if it ever does: don't update current/previous, just bail out 74 | return org.eclipse.jface.text.rules.Token.UNDEFINED; 75 | } 76 | 77 | current = next; 78 | next = afterNext; 79 | afterNext = (CommonToken) token; 80 | 81 | if (current.getType() == Token.EOF) { 82 | return org.eclipse.jface.text.rules.Token.EOF; 83 | } 84 | 85 | if (current.getType() == JSONLexer.WS) { 86 | return org.eclipse.jface.text.rules.Token.WHITESPACE; 87 | } 88 | 89 | int currentType = current.getType(); 90 | int nextType = next.getType(); 91 | int afterNextType = afterNext.getType(); 92 | TokenStyle style = getStyle(currentType, nextType, afterNextType); 93 | TextAttribute data = tokenStyler.apply(style); 94 | 95 | return new org.eclipse.jface.text.rules.Token(data); 96 | } 97 | 98 | @Override 99 | public int getTokenOffset() { 100 | return offset + current.getStartIndex(); 101 | } 102 | 103 | @Override 104 | public int getTokenLength() { 105 | return current.getStopIndex() - current.getStartIndex() + 1; 106 | } 107 | 108 | private TokenStyle getStyle(int currentType, int nextType, int afterNextType) { 109 | switch (currentType) { 110 | case JSONLexer.STRING: 111 | // There could be whitespace between current and the next (real) token 112 | // we therefore need to look two tokens ahead 113 | if (nextType == JSONLexer.COLON || (nextType == JSONLexer.WS && afterNextType == JSONLexer.COLON)) { 114 | return TokenStyle.KEY; 115 | } else { 116 | return TokenStyle.TEXT; 117 | } 118 | 119 | case JSONLexer.NUMBER: 120 | return TokenStyle.NUMBER; 121 | 122 | case JSONLexer.TRUE: 123 | case JSONLexer.FALSE: 124 | return TokenStyle.BOOLEAN; 125 | 126 | case JSONLexer.NULL: 127 | return TokenStyle.NULL; 128 | 129 | case JSONLexer.LINE_COMMENT: 130 | case JSONLexer.BLOCK_COMMENT: 131 | return TokenStyle.COMMENT; 132 | 133 | default: 134 | return TokenStyle.DEFAULT; 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /jsonedit-model/src/main/java/com/boothen/jsonedit/model/JsonContextTokenFinder.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.model; 2 | 3 | import java.util.Map; 4 | 5 | import org.antlr.v4.runtime.tree.ErrorNode; 6 | import org.antlr.v4.runtime.tree.ParseTree; 7 | import org.antlr.v4.runtime.tree.RuleNode; 8 | import org.antlr.v4.runtime.tree.TerminalNode; 9 | import org.eclipse.jface.text.Position; 10 | 11 | import com.boothen.jsonedit.antlr.JSONBaseVisitor; 12 | 13 | /** 14 | * Recurses into tree finding the smallest node that fully contains the specified text segment. 15 | */ 16 | public class JsonContextTokenFinder extends JSONBaseVisitor { 17 | 18 | private int textStart; 19 | private int textStop; 20 | private Map positions; 21 | 22 | /** 23 | * Takes a range of selected text 24 | * @param textStart the text start marker 25 | * @param textStop the text stop marker 26 | * @param positions maps tree elements to document positions 27 | */ 28 | public JsonContextTokenFinder(int textStart, int textStop, Map positions) { 29 | this.textStart = textStart; 30 | this.textStop = textStop; 31 | this.positions = positions; 32 | } 33 | 34 | @Override 35 | public ParseTree visitChildren(RuleNode node) { 36 | if (!fullyInside(node)) { 37 | return null; 38 | } 39 | 40 | // node matches, but we try to find a child 41 | // element that fits even better 42 | for (int i = 0; i < node.getChildCount(); i++) { 43 | ParseTree child = node.getChild(i); 44 | ParseTree childResult = child.accept(this); 45 | if (childResult != null) { 46 | return childResult; 47 | } 48 | } 49 | 50 | return node; 51 | } 52 | 53 | @Override 54 | public ParseTree visitTerminal(TerminalNode node) { 55 | return fullyInside(node) ? node : null; 56 | } 57 | 58 | @Override 59 | public ParseTree visitErrorNode(ErrorNode node) { 60 | // TODO examine what to do here 61 | return super.visitErrorNode(node); 62 | } 63 | 64 | private boolean fullyInside(ParseTree treeNode) { 65 | Position segment = positions.get(treeNode); 66 | if (segment == null) { 67 | // bail out on an erroneous and unknown nodes 68 | return false; 69 | } 70 | 71 | return (segment.getOffset() <= textStart && textStop <= segment.getOffset() + segment.getLength()); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /jsonedit-model/src/main/java/com/boothen/jsonedit/model/ParseProblem.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.model; 2 | 3 | import org.eclipse.core.resources.IMarker; 4 | 5 | /** 6 | * Describes a parsing problem with the input document 7 | */ 8 | public class ParseProblem { 9 | 10 | public static enum Severity { 11 | INFO(IMarker.SEVERITY_INFO), 12 | WARNING(IMarker.SEVERITY_WARNING), 13 | ERROR(IMarker.SEVERITY_ERROR); 14 | 15 | private int markerValue; 16 | 17 | Severity(int markerValue) { 18 | this.markerValue = markerValue; 19 | } 20 | 21 | /** 22 | * @return the markerValue 23 | */ 24 | public int getMarkerValue() { 25 | return markerValue; 26 | } 27 | } 28 | 29 | private final String msg; 30 | private final int line; 31 | private final int startPositionInLine; 32 | private final int endPositionInLine; 33 | private final Severity severity; 34 | 35 | /** 36 | * @param severity the severity of the problem 37 | * @param msg the problem message to emit 38 | * @param line the line number in the input where the error occurred 39 | * @param start The start position within that line where the error occurred 40 | * @param end The end position within that line where the error occurred 41 | */ 42 | public ParseProblem(Severity severity, String msg, int line, int start, int end) { 43 | this.msg = msg; 44 | this.line = line; 45 | this.startPositionInLine = start; 46 | this.endPositionInLine = end; 47 | this.severity = severity; 48 | } 49 | 50 | /** 51 | * @return the message to emit 52 | */ 53 | public String getMessage() { 54 | return msg; 55 | } 56 | 57 | /** 58 | * @return line number in the input where the error occurred 59 | */ 60 | public int getLine() { 61 | return line; 62 | } 63 | 64 | /** 65 | * @return The start position within that line where the error occurred 66 | */ 67 | public int getStartPositionInLine() { 68 | return startPositionInLine; 69 | } 70 | 71 | /** 72 | * @return The end position within that line where the error occurred 73 | */ 74 | public int getEndPositionInLine() { 75 | return endPositionInLine; 76 | } 77 | 78 | /** 79 | * @return the severity of the problem 80 | */ 81 | public Severity getSeverity() { 82 | return severity; 83 | } 84 | } -------------------------------------------------------------------------------- /jsonedit-model/src/main/java/com/boothen/jsonedit/model/ParseResult.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.model; 2 | 3 | import java.util.Collections; 4 | import java.util.List; 5 | 6 | import com.boothen.jsonedit.antlr.JSONParser.JsonContext; 7 | 8 | /** 9 | * Describes the result of a parsing operation 10 | */ 11 | public class ParseResult { 12 | private final JsonContext tree; 13 | private final List lexerErrors; 14 | private final List parserErrors; 15 | 16 | /** 17 | * @param jsonTree the JSON root element 18 | * @param lexerErrors a list of lexer errors 19 | * @param parserErrors a list of parser errors 20 | */ 21 | public ParseResult(JsonContext jsonTree, List lexerErrors, List parserErrors) { 22 | this.tree = jsonTree; 23 | this.lexerErrors = lexerErrors; 24 | this.parserErrors = parserErrors; 25 | } 26 | 27 | /** 28 | * @return the JSON root element 29 | */ 30 | public JsonContext getTree() { 31 | return tree; 32 | } 33 | 34 | /** 35 | * @return a list of lexer errors 36 | */ 37 | public List getLexerErrors() { 38 | return Collections.unmodifiableList(lexerErrors); 39 | } 40 | 41 | /** 42 | * @return a list of parser problems 43 | */ 44 | public List getParserErrors() { 45 | return Collections.unmodifiableList(parserErrors); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /jsonedit-model/src/main/java/com/boothen/jsonedit/model/ParseTreeInfo.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.model; 2 | 3 | import org.antlr.v4.runtime.ParserRuleContext; 4 | import org.antlr.v4.runtime.tree.ParseTree; 5 | import org.antlr.v4.runtime.tree.TerminalNode; 6 | 7 | /** 8 | * 9 | */ 10 | public class ParseTreeInfo { 11 | 12 | /** 13 | * @param treeNode the node to inspect 14 | * @return a segment describing the corresponding text range in the document or null. 15 | */ 16 | public static Segment getSegment(ParseTree treeNode) { 17 | if (treeNode instanceof ParserRuleContext) { 18 | ParserRuleContext ctx = (ParserRuleContext) treeNode; 19 | if (ctx.exception == null) { 20 | int start = ctx.start.getStartIndex(); 21 | // stop token is null if the whole tree is just EOF (document out of sync) 22 | int stop = (ctx.stop != null) ? ctx.stop.getStopIndex() : start; 23 | return new Segment(start, stop); 24 | } 25 | } 26 | if (treeNode instanceof TerminalNode) { 27 | TerminalNode t = (TerminalNode) treeNode; 28 | int start = t.getSymbol().getStartIndex(); 29 | int stop = t.getSymbol().getStopIndex(); 30 | return new Segment(start, stop); 31 | } 32 | 33 | return null; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /jsonedit-model/src/main/java/com/boothen/jsonedit/model/Segment.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.model; 2 | 3 | public class Segment { 4 | private int start; 5 | private int stop; 6 | 7 | public Segment(int start, int stop) { 8 | this.start = start; 9 | this.stop = stop; 10 | } 11 | 12 | public int getStart() { 13 | return start; 14 | } 15 | 16 | public int getStop() { 17 | return stop; 18 | } 19 | 20 | public int getLength() { 21 | return stop - start + 1; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /jsonedit-model/src/main/java/com/boothen/jsonedit/model/TokenStyler.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.model; 2 | 3 | import org.eclipse.jface.text.TextAttribute; 4 | 5 | import com.boothen.jsonedit.core.preferences.TokenStyle; 6 | 7 | /** 8 | * Defines and applies text representations for {@link TokenStyle} instances. 9 | */ 10 | public interface TokenStyler { 11 | 12 | /** 13 | * @param style the token style 14 | * @return a JFace text attribute that defines the styling (color, font modifiers) for the given token 15 | */ 16 | TextAttribute apply(TokenStyle style); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /jsonedit-model/src/main/java/com/boothen/jsonedit/problems/DuplicateKeyFinder.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.problems; 2 | 3 | import java.util.Collection; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | import org.antlr.v4.runtime.Token; 8 | import org.antlr.v4.runtime.tree.ParseTree; 9 | 10 | import com.boothen.jsonedit.antlr.JSONBaseVisitor; 11 | import com.boothen.jsonedit.antlr.JSONParser.ObjectContext; 12 | import com.boothen.jsonedit.antlr.JSONParser.PairContext; 13 | import com.boothen.jsonedit.model.ParseProblem; 14 | import com.boothen.jsonedit.model.ParseProblem.Severity; 15 | 16 | /** 17 | * Recurses into tree finding all duplicate keys. 18 | */ 19 | public class DuplicateKeyFinder extends JSONBaseVisitor { 20 | 21 | private final Collection problems; 22 | 23 | /** 24 | * @param problems the list of problems that will receive all found encountered problems 25 | */ 26 | public DuplicateKeyFinder(Collection problems) { 27 | this.problems = problems; 28 | } 29 | 30 | @Override 31 | public Void visitObject(ObjectContext ctx) { 32 | Map keys = new HashMap<>(); 33 | for (int i = 0; i < ctx.getChildCount(); i++) { 34 | ParseTree child = ctx.getChild(i); 35 | if (child instanceof PairContext) { 36 | PairContext pair = (PairContext) child; 37 | // Evaluate successful rule matches only 38 | if (pair.exception == null) { 39 | Token keyToken = pair.STRING().getSymbol(); 40 | String key = keyToken.getText(); 41 | Token existing = keys.put(key, keyToken); 42 | if (existing != null) { 43 | reportDuplicate(key, existing, keyToken); 44 | } 45 | } 46 | } 47 | } 48 | return super.visitObject(ctx); 49 | } 50 | 51 | private void reportDuplicate(String key, Token first, Token second) { 52 | String errorMessage = String.format("Duplicate key: %s - already at line %d: [%d]", 53 | key, first.getLine(), first.getCharPositionInLine()); 54 | int line = second.getLine(); 55 | int startPos = second.getCharPositionInLine(); 56 | int endPos = startPos + second.getText().length(); 57 | problems.add(new ParseProblem(Severity.WARNING, errorMessage, line, startPos, endPos)); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /jsonedit-model/src/main/java/com/boothen/jsonedit/problems/StringProblemFinder.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.problems; 2 | 3 | import java.util.Collection; 4 | import java.util.regex.Matcher; 5 | import java.util.regex.Pattern; 6 | 7 | import org.antlr.v4.runtime.Token; 8 | import org.antlr.v4.runtime.tree.TerminalNode; 9 | 10 | import com.boothen.jsonedit.antlr.JSONBaseVisitor; 11 | import com.boothen.jsonedit.antlr.JSONParser.ValueContext; 12 | import com.boothen.jsonedit.model.ParseProblem; 13 | import com.boothen.jsonedit.model.ParseProblem.Severity; 14 | 15 | /** 16 | * Recurses into tree finding all string-related problems. 17 | */ 18 | public class StringProblemFinder extends JSONBaseVisitor { 19 | 20 | // Do a negative lookahead for [bnfrt\/"] or uXXXX (four digit hex code) 21 | // Original pattern: \\(?![bnfrt\/"]|u[0-9a-fA-F]{4}). 22 | private static final Pattern UNESCAPED_UNSAFE = Pattern.compile("\\\\(?![bnfrt\\/\"]|u[0-9a-fA-F]{4})."); 23 | 24 | private final Collection problems; 25 | 26 | /** 27 | * @param problems the list of problems that will receive all found encountered problems 28 | */ 29 | public StringProblemFinder(Collection problems) { 30 | this.problems = problems; 31 | } 32 | 33 | @Override 34 | public Void visitValue(ValueContext ctx) { 35 | TerminalNode s = ctx.STRING(); 36 | if (s != null) { 37 | checkEscaping(s.getSymbol()); 38 | } 39 | 40 | return super.visitValue(ctx); 41 | } 42 | 43 | private void checkEscaping(Token token) { 44 | // replace double-occurrences of backslash to identify odd numbers only 45 | // this will make it work for \\\ too 46 | String text = token.getText().replace("\\\\", "__"); // preserve length 47 | 48 | Matcher matcher = UNESCAPED_UNSAFE.matcher(text); 49 | while (matcher.find()) { 50 | report(token, matcher); 51 | } 52 | } 53 | 54 | private void report(Token token, Matcher matcher) { 55 | String text = matcher.group(); 56 | String errorMessage = String.format("Escaping is not allowed in ECMA-404 for '%s'", text); 57 | int line = token.getLine(); 58 | int posInLine = token.getCharPositionInLine() + matcher.start(); 59 | int endPos = posInLine + text.length(); 60 | problems.add(new ParseProblem(Severity.WARNING, errorMessage, line, posInLine, endPos)); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /jsonedit-outline/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Bundle-ManifestVersion: 2 3 | Bundle-Name: JSON Editor Outline View 4 | Bundle-SymbolicName: jsonedit-outline 5 | Bundle-Version: 1.1.3 6 | Bundle-RequiredExecutionEnvironment: JavaSE-1.7 7 | Bundle-Vendor: Boothen Technology 8 | Require-Bundle: org.eclipse.jface.text, 9 | org.eclipse.ui, 10 | org.eclipse.ui.views, 11 | org.eclipse.ui.editors, 12 | org.eclipse.core.runtime, 13 | jsonedit-model, 14 | org.antlr.antlr4-runtime, 15 | jsonedit-preferences 16 | Export-Package: com.boothen.jsonedit.outline, 17 | com.boothen.jsonedit.quickoutline 18 | Bundle-ActivationPolicy: lazy 19 | Bundle-Activator: com.boothen.jsonedit.outline.Activator 20 | Import-Package: com.boothen.jsonedit.core, 21 | com.boothen.jsonedit.text 22 | -------------------------------------------------------------------------------- /jsonedit-outline/build.properties: -------------------------------------------------------------------------------- 1 | source.. = src/main/java 2 | output.. = target/classes 3 | bin.includes = META-INF/,\ 4 | .,\ 5 | icons/ 6 | 7 | -------------------------------------------------------------------------------- /jsonedit-outline/icons/JsonArray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boothen/Json-Eclipse-Plugin/68da2e573116f3e452066db9d985dff48638d88e/jsonedit-outline/icons/JsonArray.png -------------------------------------------------------------------------------- /jsonedit-outline/icons/JsonBoolean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boothen/Json-Eclipse-Plugin/68da2e573116f3e452066db9d985dff48638d88e/jsonedit-outline/icons/JsonBoolean.png -------------------------------------------------------------------------------- /jsonedit-outline/icons/JsonError.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boothen/Json-Eclipse-Plugin/68da2e573116f3e452066db9d985dff48638d88e/jsonedit-outline/icons/JsonError.png -------------------------------------------------------------------------------- /jsonedit-outline/icons/JsonNull.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boothen/Json-Eclipse-Plugin/68da2e573116f3e452066db9d985dff48638d88e/jsonedit-outline/icons/JsonNull.png -------------------------------------------------------------------------------- /jsonedit-outline/icons/JsonNumber.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boothen/Json-Eclipse-Plugin/68da2e573116f3e452066db9d985dff48638d88e/jsonedit-outline/icons/JsonNumber.png -------------------------------------------------------------------------------- /jsonedit-outline/icons/JsonObject.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boothen/Json-Eclipse-Plugin/68da2e573116f3e452066db9d985dff48638d88e/jsonedit-outline/icons/JsonObject.png -------------------------------------------------------------------------------- /jsonedit-outline/icons/JsonString.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boothen/Json-Eclipse-Plugin/68da2e573116f3e452066db9d985dff48638d88e/jsonedit-outline/icons/JsonString.png -------------------------------------------------------------------------------- /jsonedit-outline/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | 7 | com.boothen 8 | jsonedit-parent 9 | 1.1.3 10 | 11 | 12 | jsonedit-outline 13 | eclipse-plugin 14 | 15 | 16 | -------------------------------------------------------------------------------- /jsonedit-outline/src/main/java/com/boothen/jsonedit/outline/Activator.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.outline; 2 | 3 | import org.eclipse.jface.resource.ImageDescriptor; 4 | import org.eclipse.ui.plugin.AbstractUIPlugin; 5 | 6 | /** 7 | * The activator class controls the plug-in life cycle 8 | */ 9 | public class Activator extends AbstractUIPlugin { 10 | 11 | /** 12 | * The plug-in ID 13 | */ 14 | public static final String PLUGIN_ID = "jsonedit-outline"; //$NON-NLS-1$ 15 | 16 | /** 17 | * Returns an image descriptor for the image file at the given plug-in relative path 18 | * @param path the path 19 | * @return the image descriptor 20 | */ 21 | public static ImageDescriptor getImageDescriptor(String path) { 22 | return imageDescriptorFromPlugin(PLUGIN_ID, path); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /jsonedit-outline/src/main/java/com/boothen/jsonedit/outline/Container.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.outline; 2 | 3 | /** 4 | * Looks the same to the outside, but may change on the inside 5 | * @param the type of the contained object 6 | */ 7 | public final class Container { 8 | 9 | private T content; 10 | 11 | /** 12 | * Uses null content. 13 | */ 14 | public Container() { 15 | this(null); 16 | } 17 | 18 | /** 19 | * @param content the content to wrap 20 | */ 21 | public Container(T content) { 22 | this.content = content; 23 | } 24 | 25 | /** 26 | * @return the content 27 | */ 28 | public T getContent() { 29 | return content; 30 | } 31 | 32 | /** 33 | * @param content the content to set 34 | */ 35 | public void setContent(T content) { 36 | this.content = content; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /jsonedit-outline/src/main/java/com/boothen/jsonedit/outline/JsonContentProvider.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2014 Boothen Technology Ltd. 3 | * 4 | * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://eclipse.org/org/documents/epl-v10.html 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *******************************************************************************/ 16 | /** 17 | * 18 | */ 19 | package com.boothen.jsonedit.outline; 20 | 21 | import java.util.Collections; 22 | import java.util.List; 23 | import java.util.Map; 24 | 25 | import org.antlr.v4.runtime.ParserRuleContext; 26 | import org.antlr.v4.runtime.tree.ParseTree; 27 | import org.eclipse.jface.viewers.ITreeContentProvider; 28 | import org.eclipse.jface.viewers.Viewer; 29 | 30 | /** 31 | * Provides the Tree Structure for the outline view. 32 | * It uses the original syntax tree as provided by ANTLR. 33 | */ 34 | public class JsonContentProvider implements ITreeContentProvider { 35 | 36 | private final JsonContextTreeFilter treeFilter = new JsonContextTreeFilter(); 37 | private final ParentProvider parentProvider = new ParentProvider(this); 38 | private Map parents = Collections.emptyMap(); 39 | 40 | @Override 41 | public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { 42 | // must be implemented 43 | } 44 | 45 | @Override 46 | public Object[] getElements(Object inputElement) { 47 | // the root input element is wrapped a Container 48 | Container container = (Container) inputElement; 49 | return getChildren(container.getContent()); 50 | } 51 | 52 | @Override 53 | public Object[] getChildren(Object parentElement) { 54 | if (parentElement instanceof ParserRuleContext) { 55 | ParserRuleContext context = (ParserRuleContext) parentElement; 56 | List children = context.accept(treeFilter); 57 | return children.toArray(); 58 | } 59 | 60 | return new Object[0]; 61 | } 62 | 63 | @Override 64 | public boolean hasChildren(Object element) { 65 | return getChildren(element).length > 0; 66 | } 67 | 68 | @Override 69 | public Object getParent(Object element) { 70 | Object parent = parents.get(element); 71 | return parent; 72 | } 73 | 74 | @Override 75 | public void dispose() { 76 | // must be implemented 77 | } 78 | 79 | /** 80 | * This method must be called when the content of the root container has changed. 81 | * It should be possible to derive the parent element directly, though. 82 | * @param tree the syntax tree that is walked to identify parent elements 83 | */ 84 | public void refreshParents(ParseTree tree) { 85 | parents = parentProvider.record(tree); 86 | } 87 | 88 | /** 89 | * @param element the element to test for existance in the syntax tree 90 | * @return true if known 91 | */ 92 | public boolean isKnown(ParseTree element) { 93 | return parents.containsKey(element); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /jsonedit-outline/src/main/java/com/boothen/jsonedit/outline/JsonContextImageVisitor.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.outline; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import org.antlr.v4.runtime.tree.ErrorNode; 7 | import org.antlr.v4.runtime.tree.TerminalNode; 8 | import org.eclipse.jface.resource.ImageDescriptor; 9 | import org.eclipse.swt.graphics.Image; 10 | 11 | import com.boothen.jsonedit.antlr.JSONBaseVisitor; 12 | import com.boothen.jsonedit.antlr.JSONParser; 13 | import com.boothen.jsonedit.antlr.JSONParser.ArrayContext; 14 | import com.boothen.jsonedit.antlr.JSONParser.ObjectContext; 15 | import com.boothen.jsonedit.antlr.JSONParser.PairContext; 16 | import com.boothen.jsonedit.antlr.JSONParser.ValueContext; 17 | import com.boothen.jsonedit.preferences.NodeType; 18 | 19 | /** 20 | * Visits tree nodes in the JsonContext depending on the node type. Does not recurse. 21 | */ 22 | class JsonContextImageVisitor extends JSONBaseVisitor { 23 | 24 | private final Map images = new HashMap<>(); 25 | 26 | @Override 27 | public Image visitObject(ObjectContext ctx) { 28 | return getCachedImage(NodeType.OBJECT); 29 | } 30 | 31 | @Override 32 | public Image visitArray(ArrayContext ctx) { 33 | return getCachedImage(NodeType.ARRAY); 34 | } 35 | 36 | @Override 37 | public Image visitErrorNode(ErrorNode node) { 38 | return getCachedImage(NodeType.ERROR); 39 | } 40 | 41 | @Override 42 | public Image visitPair(PairContext ctx) { 43 | ValueContext value = ctx.value(); 44 | 45 | if (value.exception != null) { 46 | return getCachedImage(NodeType.ERROR); 47 | } 48 | 49 | TerminalNode node = value.getChild(TerminalNode.class, 0); 50 | if (node != null) { 51 | return visitTerminal(node); 52 | } 53 | 54 | return visit(value.getChild(0)); 55 | } 56 | 57 | @Override 58 | public Image visitTerminal(TerminalNode node) { 59 | switch (node.getSymbol().getType()) { 60 | case JSONParser.NUMBER: 61 | return getCachedImage(NodeType.NUMBER); 62 | case JSONParser.TRUE: 63 | case JSONParser.FALSE: 64 | return getCachedImage(NodeType.BOOLEAN); 65 | case JSONParser.STRING: 66 | return getCachedImage(NodeType.STRING); 67 | case JSONParser.NULL: 68 | return getCachedImage(NodeType.NULL); 69 | default: 70 | return null; 71 | } 72 | } 73 | 74 | private Image getCachedImage(NodeType key) { 75 | Image image = images.get(key); 76 | if (image == null) { 77 | String path = key.getImagePath(); 78 | ImageDescriptor desc = Activator.getImageDescriptor("/icons/" + path); 79 | if (desc != null) { 80 | image = desc.createImage(); 81 | images.put(key, image); 82 | } 83 | } 84 | return image; 85 | } 86 | 87 | public void dispose() { 88 | for (Image img : images.values()) { 89 | img.dispose(); 90 | } 91 | images.clear(); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /jsonedit-outline/src/main/java/com/boothen/jsonedit/outline/JsonContextLabelVisitor.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.outline; 2 | 3 | import org.antlr.v4.runtime.Token; 4 | import org.antlr.v4.runtime.tree.ErrorNode; 5 | import org.antlr.v4.runtime.tree.TerminalNode; 6 | import org.eclipse.jface.preference.IPreferenceStore; 7 | import org.eclipse.jface.text.TextAttribute; 8 | import org.eclipse.jface.viewers.StyledString; 9 | import org.eclipse.jface.viewers.StyledString.Styler; 10 | import org.eclipse.swt.custom.StyleRange; 11 | import org.eclipse.swt.graphics.TextStyle; 12 | 13 | import com.boothen.jsonedit.antlr.JSONBaseVisitor; 14 | import com.boothen.jsonedit.antlr.JSONParser; 15 | import com.boothen.jsonedit.antlr.JSONParser.ArrayContext; 16 | import com.boothen.jsonedit.antlr.JSONParser.ObjectContext; 17 | import com.boothen.jsonedit.antlr.JSONParser.PairContext; 18 | import com.boothen.jsonedit.antlr.JSONParser.ValueContext; 19 | import com.boothen.jsonedit.preferences.JsonTokenStyler; 20 | import com.boothen.jsonedit.preferences.NodeType; 21 | 22 | /** 23 | * Visits tree nodes in the JsonContext depending on the node type. Does not recurse. 24 | */ 25 | class JsonContextLabelVisitor extends JSONBaseVisitor { 26 | 27 | private final JsonTokenStyler tokenStyler; 28 | 29 | /** 30 | * @param preferenceStore the preference store that defines the text style 31 | */ 32 | public JsonContextLabelVisitor(IPreferenceStore preferenceStore) { 33 | this.tokenStyler = new JsonTokenStyler(preferenceStore); 34 | } 35 | 36 | @Override 37 | public StyledString visitObject(ObjectContext ctx) { 38 | return getStyledString(NodeType.OBJECT, "Object"); 39 | } 40 | 41 | @Override 42 | public StyledString visitArray(ArrayContext ctx) { 43 | return getStyledString(NodeType.ARRAY, "Array"); 44 | } 45 | 46 | @Override 47 | public StyledString visitErrorNode(ErrorNode node) { 48 | return getStyledString(NodeType.ERROR, "Error"); 49 | } 50 | 51 | @Override 52 | public StyledString visitPair(PairContext ctx) { 53 | String key = ctx.STRING().getText(); 54 | ValueContext value = ctx.value(); 55 | 56 | TerminalNode node = value.getChild(TerminalNode.class, 0); 57 | if (node != null) { 58 | NodeType type = getType(node); 59 | if (type != null) { 60 | return getStyledString(type, key, node.getText()); 61 | } 62 | } 63 | 64 | return new StyledString(key); 65 | } 66 | 67 | @Override 68 | public StyledString visitTerminal(TerminalNode node) { 69 | NodeType type = getType(node); 70 | if (type != null) { 71 | return getStyledString(type, node.getText()); 72 | } 73 | return new StyledString(); 74 | } 75 | 76 | private NodeType getType(TerminalNode node) { 77 | NodeType type = null; 78 | Token symbol = node.getSymbol(); 79 | switch (symbol.getType()) { 80 | case JSONParser.STRING: 81 | type = NodeType.STRING; 82 | break; 83 | 84 | case JSONParser.NULL: 85 | type = NodeType.NULL; 86 | break; 87 | 88 | case JSONParser.NUMBER: 89 | type = NodeType.NUMBER; 90 | break; 91 | 92 | case JSONParser.TRUE: 93 | case JSONParser.FALSE: 94 | type = NodeType.BOOLEAN; 95 | break; 96 | } 97 | return type; 98 | } 99 | 100 | private StyledString getStyledString(NodeType type, String value) { 101 | return getStyledString(type, null, value); 102 | } 103 | 104 | private StyledString getStyledString(NodeType type, String key, String value) { 105 | TextAttribute attribs = tokenStyler.apply(type.getTokenStyle()); 106 | 107 | StyledString text = new StyledString(); 108 | if (key != null) { 109 | text.append(key); 110 | text.append(": "); 111 | } 112 | text.append(value, new TextAttributeStyler(attribs)); 113 | return text; 114 | } 115 | 116 | /** 117 | * A {@link Styler} that wraps {@link TextAttribute}. 118 | */ 119 | private static class TextAttributeStyler extends Styler { 120 | private TextAttribute textAttribute; 121 | 122 | public TextAttributeStyler(TextAttribute attrib) { 123 | this.textAttribute = attrib; 124 | } 125 | 126 | @Override 127 | public void applyStyles(TextStyle textStyle) { 128 | if (textStyle instanceof StyleRange) { 129 | // for some reason, this does not have any effect 130 | final StyleRange range = (StyleRange) textStyle; 131 | range.fontStyle = textAttribute.getStyle(); 132 | } 133 | 134 | textStyle.foreground = textAttribute.getForeground(); 135 | textStyle.background = textAttribute.getBackground(); 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /jsonedit-outline/src/main/java/com/boothen/jsonedit/outline/JsonContextTreeFilter.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.outline; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | import org.antlr.v4.runtime.ParserRuleContext; 8 | import org.antlr.v4.runtime.tree.ErrorNode; 9 | import org.antlr.v4.runtime.tree.ParseTree; 10 | import org.antlr.v4.runtime.tree.TerminalNode; 11 | 12 | import com.boothen.jsonedit.antlr.JSONBaseVisitor; 13 | import com.boothen.jsonedit.antlr.JSONParser.ArrayContext; 14 | import com.boothen.jsonedit.antlr.JSONParser.JsonContext; 15 | import com.boothen.jsonedit.antlr.JSONParser.ObjectContext; 16 | import com.boothen.jsonedit.antlr.JSONParser.PairContext; 17 | import com.boothen.jsonedit.antlr.JSONParser.ValueContext; 18 | 19 | /** 20 | * Visits tree nodes in the JsonContext depending on the node type. Does not recurse. 21 | * Skips {@link ValueContext} instances. 22 | */ 23 | class JsonContextTreeFilter extends JSONBaseVisitor> { 24 | 25 | @Override 26 | public List visitJson(JsonContext ctx) { 27 | return getChildren(ctx); 28 | // Use the following to skip the root node 29 | // return visit(ctx.getChild(0)); 30 | } 31 | 32 | @Override 33 | public List visitObject(ObjectContext ctx) { 34 | return getChildren(ctx); 35 | } 36 | 37 | @Override 38 | public List visitArray(ArrayContext ctx) { 39 | List sum = new ArrayList<>(); 40 | for (ValueContext child : ctx.value()) { 41 | if (child.exception == null) { 42 | sum.add(child.getChild(0)); 43 | } 44 | } 45 | return sum; 46 | } 47 | 48 | @Override 49 | public List visitPair(PairContext ctx) { 50 | if (ctx.exception == null) { 51 | ValueContext value = ctx.value(); 52 | if (value.exception == null) { 53 | ParseTree child = value.getChild(0); 54 | return visit(child); 55 | } 56 | } 57 | 58 | return Collections.emptyList(); 59 | } 60 | 61 | @Override 62 | public List visitTerminal(TerminalNode node) { 63 | return Collections.emptyList(); 64 | } 65 | 66 | @Override 67 | public List visitErrorNode(ErrorNode node) { 68 | return Collections.emptyList(); 69 | } 70 | 71 | private List getChildren(ParseTree ctx) { 72 | List children = new ArrayList<>(); 73 | for (int i = 0; i < ctx.getChildCount(); i++) { 74 | ParseTree child = ctx.getChild(i); 75 | if (shouldAdd(child)) { 76 | children.add(child); 77 | } 78 | } 79 | return children; 80 | } 81 | 82 | private boolean shouldAdd(ParseTree child) { 83 | if (child instanceof TerminalNode) { 84 | return false; 85 | } 86 | if (child instanceof ParserRuleContext) { 87 | ParserRuleContext ctx = (ParserRuleContext) child; 88 | if (ctx.exception != null) { 89 | return false; 90 | } 91 | } 92 | return true; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /jsonedit-outline/src/main/java/com/boothen/jsonedit/outline/JsonLabelProvider.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2014 Boothen Technology Ltd. 3 | * 4 | * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://eclipse.org/org/documents/epl-v10.html 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *******************************************************************************/ 16 | /** 17 | * 18 | */ 19 | package com.boothen.jsonedit.outline; 20 | 21 | 22 | import org.antlr.v4.runtime.tree.ParseTree; 23 | import org.eclipse.jface.preference.IPreferenceStore; 24 | import org.eclipse.jface.viewers.ColumnLabelProvider; 25 | import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider; 26 | import org.eclipse.jface.viewers.StyledString; 27 | import org.eclipse.swt.graphics.Image; 28 | 29 | /** 30 | * JsonLabelProvider provides the label format for each element in the tree. 31 | */ 32 | public class JsonLabelProvider extends ColumnLabelProvider implements IStyledLabelProvider { 33 | 34 | private final JsonContextLabelVisitor contextLabelVisitor; 35 | private final JsonContextImageVisitor contextImageVisitor = new JsonContextImageVisitor(); 36 | 37 | /** 38 | * @param preferenceStore the preference store that provides the text style 39 | */ 40 | public JsonLabelProvider(IPreferenceStore preferenceStore) { 41 | contextLabelVisitor = new JsonContextLabelVisitor(preferenceStore); 42 | } 43 | 44 | /** 45 | * Returns the text contained in the tree element. 46 | */ 47 | @Override 48 | public String getText(Object element) { 49 | return getStyledText(element).toString(); 50 | } 51 | 52 | @Override 53 | public Image getImage(Object element) { 54 | if (element instanceof ParseTree) { 55 | ParseTree context = (ParseTree) element; 56 | return context.accept(contextImageVisitor); 57 | } 58 | 59 | return null; 60 | } 61 | 62 | /** 63 | * Returns the styled text contained in the tree element. 64 | */ 65 | @Override 66 | public StyledString getStyledText(Object element) { 67 | StyledString styledString = new StyledString(); 68 | if (element instanceof ParseTree) { 69 | ParseTree node = (ParseTree) element; 70 | return contextLabelVisitor.visit(node); 71 | } 72 | return styledString; 73 | } 74 | 75 | @Override 76 | public void dispose() { 77 | contextImageVisitor.dispose(); 78 | super.dispose(); 79 | } 80 | 81 | 82 | } 83 | -------------------------------------------------------------------------------- /jsonedit-outline/src/main/java/com/boothen/jsonedit/outline/ParentProvider.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.outline; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import org.eclipse.jface.viewers.ITreeContentProvider; 7 | 8 | /** 9 | * Convert the provided tree content into a map (child -> parent) 10 | */ 11 | class ParentProvider { 12 | 13 | private final ITreeContentProvider contentProvider; 14 | 15 | /** 16 | * @param contentProvider provides the tree content 17 | */ 18 | public ParentProvider(ITreeContentProvider contentProvider) { 19 | this.contentProvider = contentProvider; 20 | } 21 | 22 | /** 23 | * Iterate through the tree and serializes all child elements to a list (depth first). 24 | * @param root the tree root 25 | * @return the tree content 26 | */ 27 | public Map record(Object root) { 28 | Map list = new HashMap<>(); 29 | list.put(root, null); 30 | internalAdd(list, root); 31 | return list; 32 | } 33 | 34 | private void internalAdd(Map list, Object root) { 35 | for (Object child : contentProvider.getChildren(root)) { 36 | list.put(child, root); 37 | internalAdd(list, child); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /jsonedit-outline/src/main/java/com/boothen/jsonedit/quickoutline/NamePatternFilter.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.quickoutline; 2 | 3 | import java.util.ArrayList; 4 | import java.util.regex.Matcher; 5 | import java.util.regex.Pattern; 6 | 7 | import org.eclipse.jface.viewers.IContentProvider; 8 | import org.eclipse.jface.viewers.ILabelProvider; 9 | import org.eclipse.jface.viewers.ITreeContentProvider; 10 | import org.eclipse.jface.viewers.ITreePathContentProvider; 11 | import org.eclipse.jface.viewers.TreePath; 12 | import org.eclipse.jface.viewers.TreeViewer; 13 | import org.eclipse.jface.viewers.Viewer; 14 | import org.eclipse.jface.viewers.ViewerFilter; 15 | 16 | /** 17 | * The NamePatternFilter selects the elements which 18 | * match the given regular expression. 19 | */ 20 | public class NamePatternFilter extends ViewerFilter { 21 | 22 | private final ILabelProvider labelProvider; 23 | 24 | private Pattern pattern = Pattern.compile(".*"); 25 | 26 | /** 27 | * @param labelProvider provides the text for tree elements (e.g. implemented through ILabelProvider) 28 | */ 29 | public NamePatternFilter(ILabelProvider labelProvider) { 30 | this.labelProvider = labelProvider; 31 | } 32 | 33 | @Override 34 | public Object[] filter(Viewer viewer, TreePath parentPath, Object[] elements) { 35 | int size = elements.length; 36 | ArrayList out = new ArrayList(size); 37 | for (int i = 0; i < size; ++i) { 38 | Object element = elements[i]; 39 | if (selectTreePath(viewer, parentPath, element)) { 40 | out.add(element); 41 | } 42 | } 43 | return out.toArray(); 44 | } 45 | 46 | @Override 47 | public boolean select(Viewer viewer, Object parentElement, Object element) { 48 | return selectTreePath(viewer, new TreePath(new Object[] { parentElement }), element); 49 | } 50 | 51 | private boolean selectTreePath(Viewer viewer, TreePath parentPath, Object element) { 52 | TreeViewer treeViewer = (TreeViewer) viewer; 53 | 54 | String matchName = labelProvider.getText(element); 55 | Matcher matcher = pattern.matcher(matchName); 56 | if (matchName != null && matcher.find()) 57 | return true; 58 | 59 | return hasUnfilteredChild(treeViewer, parentPath, element); 60 | } 61 | 62 | private boolean hasUnfilteredChild(TreeViewer viewer, TreePath parentPath, Object element) { 63 | TreePath elementPath = parentPath.createChildPath(element); 64 | IContentProvider contentProvider = viewer.getContentProvider(); 65 | 66 | Object[] children = contentProvider instanceof ITreePathContentProvider 67 | ? ((ITreePathContentProvider) contentProvider).getChildren(elementPath) 68 | : ((ITreeContentProvider) contentProvider).getChildren(element); 69 | 70 | for (int i = 0; i < children.length; i++) { 71 | if (selectTreePath(viewer, elementPath, children[i])) { 72 | return true; 73 | } 74 | } 75 | return false; 76 | } 77 | 78 | /** 79 | * Sets a new regular expression that is used for filtering. Only tree elements with matching 80 | * label (as defined by the viewer's {@link ILabelProvider}) pass. 81 | * @param pattern a regular expression pattern 82 | */ 83 | public void setPattern(Pattern pattern) { 84 | this.pattern = pattern; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /jsonedit-preferences/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Bundle-ManifestVersion: 2 3 | Bundle-Name: JSON Editor Preferences 4 | Bundle-SymbolicName: jsonedit-preferences;singleton:=true 5 | Bundle-Version: 1.1.3 6 | Bundle-RequiredExecutionEnvironment: JavaSE-1.7 7 | Bundle-Localization: plugin 8 | Bundle-Vendor: Boothen Technology 9 | Require-Bundle: org.eclipse.core.resources, 10 | org.eclipse.core.runtime, 11 | org.eclipse.ui, 12 | org.eclipse.ui.editors, 13 | jsonedit-core, 14 | org.eclipse.equinox.preferences, 15 | jsonedit-model, 16 | org.eclipse.jface.text, 17 | jsonedit-text, 18 | org.antlr.antlr4-runtime 19 | Export-Package: com.boothen.jsonedit.preferences; 20 | uses:="org.eclipse.ui, 21 | org.eclipse.swt.events, 22 | org.eclipse.jface.util, 23 | org.eclipse.jface.text, 24 | org.eclipse.jface.preference, 25 | org.eclipse.swt.widgets, 26 | org.eclipse.jface.viewers", 27 | com.boothen.jsonedit.preferences.format; 28 | uses:="org.eclipse.ui, 29 | org.eclipse.swt.events, 30 | org.eclipse.jface.util, 31 | org.eclipse.swt.graphics, 32 | org.eclipse.jface.preference, 33 | org.eclipse.swt.widgets, 34 | org.eclipse.core.runtime.preferences" 35 | Bundle-ActivationPolicy: lazy 36 | Bundle-Activator: com.boothen.jsonedit.preferences.Activator 37 | -------------------------------------------------------------------------------- /jsonedit-preferences/build.properties: -------------------------------------------------------------------------------- 1 | source.. = src/main/java 2 | output.. = target/classes 3 | bin.includes = META-INF/,\ 4 | .,\ 5 | plugin.xml,\ 6 | plugin.properties,\ 7 | formatter_example.json,\ 8 | coloring_example.json 9 | -------------------------------------------------------------------------------- /jsonedit-preferences/coloring_example.json: -------------------------------------------------------------------------------- 1 | "key" : "string", 2 | "key" : -12.0e+13, 3 | "key" : null, // comments are not allowed in the JSON standard 4 | "key" : true, 5 | "key" : {"key" : "string"}, 6 | "key" : [1, 2, 3] 7 | -------------------------------------------------------------------------------- /jsonedit-preferences/formatter_example.json: -------------------------------------------------------------------------------- 1 | { 2 | "k1": "val", 3 | "k2": 4 | { 5 | "k": "val" 6 | }, 7 | 8 | "k3": 9 | [ 10 | 11, 11 | 22, 12 | { 13 | "k": "val" 14 | }, 15 | 16 | 44 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /jsonedit-preferences/plugin.properties: -------------------------------------------------------------------------------- 1 | #Eclipse messages class 2 | jsonPresentation.label=JSON Editor 3 | jsonEditorFontDefinition.label=JSON text font 4 | jsonEditorFontDefinition.description=The JSON editor text font is used by JSON editors. 5 | 6 | -------------------------------------------------------------------------------- /jsonedit-preferences/plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 11 | 12 | 16 | 17 | 22 | 23 | 24 | 26 | 29 | 30 | 35 | 36 | %jsonEditorFontDefinition.description 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /jsonedit-preferences/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | 7 | com.boothen 8 | jsonedit-parent 9 | 1.1.3 10 | 11 | 12 | jsonedit-preferences 13 | eclipse-plugin 14 | 15 | 16 | -------------------------------------------------------------------------------- /jsonedit-preferences/src/main/java/com/boothen/jsonedit/preferences/Activator.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.preferences; 2 | 3 | import org.eclipse.jface.resource.JFaceResources; 4 | import org.eclipse.ui.plugin.AbstractUIPlugin; 5 | import org.osgi.framework.BundleContext; 6 | 7 | /** 8 | * This plugin's activator. 9 | */ 10 | public class Activator extends AbstractUIPlugin { 11 | 12 | /** 13 | * The plug-in ID 14 | */ 15 | public static final String PLUGIN_ID = "jsonedit-preferences"; 16 | 17 | /** 18 | * The font ID of JSON text editor. Query with {@link JFaceResources#getFont}. 19 | */ 20 | public static final String FONT_ID = "com.boothen.jsonedit.fonts.textfont"; 21 | 22 | private static Activator plugin; 23 | 24 | @Override 25 | public void start(BundleContext context) throws Exception { 26 | super.start(context); 27 | plugin = this; 28 | } 29 | 30 | @Override 31 | public void stop(BundleContext context) throws Exception { 32 | super.stop(context); 33 | plugin = null; 34 | } 35 | 36 | /** 37 | * Returns the shared instance 38 | * @return the shared instance 39 | */ 40 | public static Activator getDefault() { 41 | return plugin; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /jsonedit-preferences/src/main/java/com/boothen/jsonedit/preferences/JsonRootPreferencePage.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.preferences; 2 | 3 | import org.eclipse.jface.preference.PreferencePage; 4 | import org.eclipse.swt.SWT; 5 | import org.eclipse.swt.graphics.Color; 6 | import org.eclipse.swt.widgets.Composite; 7 | import org.eclipse.swt.widgets.Control; 8 | import org.eclipse.ui.IWorkbench; 9 | import org.eclipse.ui.IWorkbenchPreferencePage; 10 | 11 | /** 12 | * The (empty) root preference page. Mainly used as identifier. 13 | */ 14 | public class JsonRootPreferencePage extends PreferencePage implements IWorkbenchPreferencePage { 15 | 16 | /** 17 | * The only constructor 18 | */ 19 | public JsonRootPreferencePage() { 20 | setDescription("Expand the tree to edit preferences for a specific feature."); 21 | noDefaultAndApplyButton(); 22 | } 23 | 24 | @Override 25 | protected final Control createContents(Composite parent) { 26 | Color widgetBackground = parent.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND); 27 | parent.setBackground(widgetBackground); 28 | 29 | return new Composite(parent, SWT.NULL); 30 | } 31 | 32 | @Override 33 | public void init(IWorkbench workbench) { 34 | // Do nothing 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /jsonedit-preferences/src/main/java/com/boothen/jsonedit/preferences/JsonTokenStyler.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.preferences; 2 | 3 | import org.eclipse.jface.preference.IPreferenceStore; 4 | import org.eclipse.jface.resource.StringConverter; 5 | import org.eclipse.jface.text.TextAttribute; 6 | import org.eclipse.swt.SWT; 7 | import org.eclipse.swt.graphics.Color; 8 | import org.eclipse.swt.graphics.RGB; 9 | 10 | import com.boothen.jsonedit.core.JsonColorProvider; 11 | import com.boothen.jsonedit.core.JsonCorePlugin; 12 | import com.boothen.jsonedit.core.preferences.TokenStyle; 13 | import com.boothen.jsonedit.model.TokenStyler; 14 | 15 | 16 | /** 17 | * Maps JSON token types to JFace {@link TextAttribute} instances. 18 | */ 19 | public class JsonTokenStyler implements TokenStyler { 20 | 21 | private final IPreferenceStore preferenceStore; 22 | private final JsonColorProvider colorProvider = JsonCorePlugin.getColorProvider(); 23 | 24 | /** 25 | * @param preferenceStore the store that provides {@link TokenStyle} information. 26 | */ 27 | public JsonTokenStyler(IPreferenceStore preferenceStore) { 28 | this.preferenceStore = preferenceStore; 29 | } 30 | 31 | @Override 32 | public TextAttribute apply(TokenStyle styleId) { 33 | boolean isBold = preferenceStore.getBoolean(styleId.isBold()); 34 | boolean isItalic = preferenceStore.getBoolean(styleId.isItalic()); 35 | int style = getStyle(isBold, isItalic); 36 | 37 | String colorText = preferenceStore.getString(styleId.color()); 38 | Color color = getColor(colorText); 39 | 40 | TextAttribute attribute = new TextAttribute(color, null, style); 41 | return attribute; 42 | } 43 | 44 | private Color getColor(String colorText) { 45 | RGB rgb = StringConverter.asRGB(colorText, null); 46 | return colorProvider.getColor(rgb); 47 | } 48 | 49 | private static int getStyle(boolean isBold, boolean isItalic) { 50 | int style = SWT.NORMAL; 51 | style |= isBold ? SWT.BOLD : 0; 52 | style |= isItalic ? SWT.ITALIC : 0; 53 | return style; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /jsonedit-preferences/src/main/java/com/boothen/jsonedit/preferences/NodeType.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.preferences; 2 | 3 | import com.boothen.jsonedit.core.preferences.TokenStyle; 4 | 5 | /** 6 | * Maps elements in the syntax tree to image, foreground and background color 7 | * in the outline view. 8 | */ 9 | public enum NodeType { 10 | /** 11 | * An object, wrapped in curly braces 12 | */ 13 | OBJECT("JsonObject.png", TokenStyle.DEFAULT), 14 | 15 | /** 16 | * An array of elements, wrapped in square brackets 17 | */ 18 | ARRAY("JsonArray.png", TokenStyle.DEFAULT), 19 | 20 | /** 21 | * A boolean value 22 | */ 23 | BOOLEAN("JsonBoolean.png", TokenStyle.BOOLEAN), 24 | 25 | /** 26 | * The constant null. 27 | */ 28 | NULL("JsonNull.png", TokenStyle.NULL), 29 | 30 | /** 31 | * A number, either integer or floating point 32 | */ 33 | NUMBER("JsonNumber.png", TokenStyle.NUMBER), 34 | 35 | /** 36 | * A text string 37 | */ 38 | STRING("JsonString.png", TokenStyle.TEXT), 39 | 40 | /** 41 | * An error node 42 | */ 43 | ERROR("JsonError.png", TokenStyle.ERROR); 44 | 45 | private String imagePath; 46 | private TokenStyle tokenStyle; 47 | 48 | private NodeType(String imagePath, TokenStyle tokenStyle) { 49 | this.imagePath = imagePath; 50 | this.tokenStyle = tokenStyle; 51 | } 52 | 53 | /** 54 | * @return the relative image path 55 | */ 56 | public String getImagePath() { 57 | return imagePath; 58 | } 59 | 60 | /** 61 | * @return the token style keys 62 | */ 63 | public TokenStyle getTokenStyle() { 64 | return tokenStyle; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /jsonedit-preferences/src/main/java/com/boothen/jsonedit/preferences/format/JsonContentFormatter.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.preferences.format; 2 | 3 | import org.eclipse.jface.preference.IPreferenceStore; 4 | import org.eclipse.jface.text.IDocument; 5 | import org.eclipse.jface.text.IRegion; 6 | import org.eclipse.jface.text.formatter.FormattingContext; 7 | import org.eclipse.jface.text.formatter.FormattingContextProperties; 8 | import org.eclipse.jface.text.formatter.IContentFormatter; 9 | import org.eclipse.jface.text.formatter.IContentFormatterExtension; 10 | import org.eclipse.jface.text.formatter.IFormattingContext; 11 | import org.eclipse.jface.text.formatter.IFormattingStrategy; 12 | 13 | /** 14 | * An eclipse content formatter that formats using a {@link JsonFormatStrategy}. 15 | */ 16 | public class JsonContentFormatter implements IContentFormatter, IContentFormatterExtension { 17 | 18 | private final JsonFormatStrategy strategy; 19 | 20 | /** 21 | * Takes a store that contains general text editor settings such as tab width, but also token-specifics. 22 | * @param store the store that provides the format settings 23 | */ 24 | public JsonContentFormatter(IPreferenceStore store) { 25 | strategy = new JsonFormatStrategy(store); 26 | } 27 | 28 | @Override 29 | public void format(IDocument document, IRegion region) { 30 | IFormattingContext context = new FormattingContext(); 31 | context.setProperty(FormattingContextProperties.CONTEXT_REGION, region); 32 | format(document, context); 33 | } 34 | 35 | @Override 36 | public void format(IDocument document, IFormattingContext context) { 37 | context.setProperty(FormattingContextProperties.CONTEXT_MEDIUM, document); 38 | strategy.formatterStarts(context); 39 | strategy.format(); 40 | strategy.formatterStops(); 41 | } 42 | 43 | @Override 44 | public IFormattingStrategy getFormattingStrategy(String contentType) { 45 | if (IDocument.DEFAULT_CONTENT_TYPE.equals(contentType)) { 46 | return strategy; 47 | } 48 | 49 | return null; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /jsonedit-preferences/src/main/java/com/boothen/jsonedit/preferences/format/JsonFormatStrategy.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.preferences.format; 2 | 3 | import org.antlr.v4.runtime.ANTLRInputStream; 4 | import org.eclipse.jface.preference.IPreferenceStore; 5 | import org.eclipse.jface.text.BadLocationException; 6 | import org.eclipse.jface.text.IDocument; 7 | import org.eclipse.jface.text.Region; 8 | import org.eclipse.jface.text.TextUtilities; 9 | import org.eclipse.jface.text.formatter.ContextBasedFormattingStrategy; 10 | import org.eclipse.jface.text.formatter.FormattingContextProperties; 11 | import org.eclipse.jface.text.formatter.IFormattingContext; 12 | 13 | import com.boothen.jsonedit.antlr.JSONLexer; 14 | import com.boothen.jsonedit.core.JsonLog; 15 | import com.boothen.jsonedit.core.preferences.JsonPreferences; 16 | 17 | /** 18 | * A formatting strategy that extract information from the formatting context and delegates 19 | * the formatting to a {@link JsonFormatter}. 20 | *

21 | * Appends a trailing newline, if {@link JsonPreferences#EDITOR_TRAILING_NEWLINE} is set. 22 | */ 23 | public class JsonFormatStrategy extends ContextBasedFormattingStrategy { 24 | 25 | private final IPreferenceStore store; 26 | private IDocument document; 27 | private Region region; 28 | 29 | /** 30 | * @param store the store that defines the format style 31 | */ 32 | public JsonFormatStrategy(IPreferenceStore store) { 33 | this.store = store; 34 | } 35 | 36 | @Override 37 | public void formatterStarts(IFormattingContext context) { 38 | super.formatterStarts(context); 39 | region = (Region) context.getProperty(FormattingContextProperties.CONTEXT_REGION); 40 | document = (IDocument) context.getProperty(FormattingContextProperties.CONTEXT_MEDIUM); 41 | if (region == null) { 42 | region = new Region(0, document.getLength()); 43 | } 44 | } 45 | 46 | @Override 47 | public void format() { 48 | 49 | String delimiter = TextUtilities.getDefaultLineDelimiter(document); 50 | JsonFormatter formatter = new JsonFormatter(delimiter, store); 51 | 52 | try { 53 | int endOffset = region.getOffset() + region.getLength(); 54 | // must be computed before the document is changed (formatted) 55 | boolean endIncluded = (endOffset == document.getLength()); 56 | 57 | int lineStartOffset = getLineStartOffset(region.getOffset()); 58 | int lineEndOffset = getLineEndOffset(endOffset); 59 | 60 | String content = document.get(0, lineEndOffset); 61 | JSONLexer lexer = new JSONLexer(new ANTLRInputStream(content)); 62 | lexer.removeErrorListeners(); 63 | 64 | String format = formatter.format(lineStartOffset, lexer); 65 | document.replace(lineStartOffset, lineEndOffset - lineStartOffset, format); 66 | 67 | boolean appendNewline = store.getBoolean(JsonPreferences.EDITOR_TRAILING_NEWLINE); 68 | if (appendNewline && endIncluded) { 69 | char lastChar = format.charAt(format.length() - 1); 70 | // not necessarily the usual delimiter - checking "\n" covers "\r\n" endings as well 71 | if (lastChar != '\n') { 72 | // document end index was changed by the replace op. so get it again 73 | document.replace(document.getLength(), 0, delimiter); 74 | } 75 | } 76 | } catch (BadLocationException e) { 77 | JsonLog.logError("Unable to format JSON region", e); 78 | } 79 | } 80 | 81 | private int getLineStartOffset(int offset) throws BadLocationException { 82 | return document.getLineInformationOfOffset(offset).getOffset(); 83 | } 84 | 85 | private int getLineEndOffset(int offset) throws BadLocationException { 86 | int line = document.getLineOfOffset(offset); 87 | // getLineLength() includes the line delimiter in contrast to getLineInformation() 88 | return document.getLineOffset(line) + document.getLineLength(line); 89 | } 90 | 91 | @Override 92 | public void formatterStops() { 93 | super.formatterStops(); 94 | document = null; 95 | region = null; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /jsonedit-preferences/src/main/java/com/boothen/jsonedit/preferences/format/JsonIndenter.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.preferences.format; 2 | 3 | import java.util.Arrays; 4 | 5 | import org.antlr.v4.runtime.Token; 6 | 7 | import com.boothen.jsonedit.antlr.JSONLexer; 8 | 9 | /** 10 | * Indents JSON code snippets. 11 | */ 12 | public class JsonIndenter { 13 | 14 | private final int tabWidth; 15 | private final boolean spacesForTabs; 16 | private int level; 17 | 18 | /** 19 | * @param tabWidth width of a tab, measured in spaces 20 | * @param spacesForTabs true if spaces should be used for indentation instead of tabs 21 | */ 22 | public JsonIndenter(int tabWidth, boolean spacesForTabs) { 23 | this.tabWidth = tabWidth; 24 | this.spacesForTabs = spacesForTabs; 25 | } 26 | 27 | /** 28 | * Updates the current indentation level based on the supplied token 29 | * @param token the token to scan 30 | */ 31 | public void updateIndentLevel(Token token) { 32 | if (increasesIndent(token)) { 33 | increaseIndent(); 34 | } 35 | 36 | if (decreasesIndent(token)) { 37 | decreaseIndent(); 38 | } 39 | } 40 | 41 | /** 42 | * Increases the indentation level 43 | */ 44 | public void increaseIndent() { 45 | level++; 46 | } 47 | 48 | /** 49 | * Decreases the indentation level 50 | */ 51 | public void decreaseIndent() { 52 | level--; 53 | } 54 | 55 | /** 56 | * @param token the token to scan 57 | * @return true if the token would increase the indentation level 58 | */ 59 | public boolean increasesIndent(Token token) { 60 | switch (token.getType()) { 61 | case JSONLexer.BEGIN_OBJECT: 62 | case JSONLexer.BEGIN_ARRAY: 63 | return true; 64 | default: 65 | return false; 66 | } 67 | } 68 | 69 | /** 70 | * @param token the token to scan 71 | * @return true if the token would decrease the indentation level 72 | */ 73 | public boolean decreasesIndent(Token token) { 74 | switch (token.getType()) { 75 | case JSONLexer.END_OBJECT: 76 | case JSONLexer.END_ARRAY: 77 | return true; 78 | default: 79 | return false; 80 | } 81 | } 82 | 83 | /** 84 | * Appends whitespace to the supplied buffer accordings to the current indentation level 85 | * @param buffer the buffer to append to 86 | */ 87 | public void indent(StringBuffer buffer) { 88 | if (level <= 0) { 89 | return; 90 | } 91 | 92 | if (spacesForTabs) { 93 | char[] array = createArray(' ', level * tabWidth); 94 | buffer.append(array); 95 | } else { 96 | char[] array = createArray('\t', level); 97 | buffer.append(array); 98 | } 99 | } 100 | 101 | private static char[] createArray(char fillChar, int length) { 102 | // TODO: consider caching the created arrays 103 | char[] array = new char[length]; 104 | Arrays.fill(array, fillChar); 105 | return array; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /jsonedit-repository/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | 7 | com.boothen 8 | jsonedit-parent 9 | 1.0.0.beta3 10 | 11 | 12 | jsonedit-repository 13 | eclipse-repository 14 | 15 | 16 | 17 | 18 | org.eclipse.tycho 19 | tycho-p2-repository-plugin 20 | ${tycho.version} 21 | 22 | false 23 | false 24 | eclipse-json-editor 25 | 26 | 27 | 28 | org.eclipse.tycho 29 | tycho-p2-director-plugin 30 | ${tycho.version} 31 | 32 | 33 | materialize-products 34 | 35 | materialize-products 36 | 37 | 38 | 39 | archive-products 40 | 41 | archive-products 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /jsonedit-site/.gitignore: -------------------------------------------------------------------------------- 1 | /content.jar 2 | /artifacts.jar 3 | /plugins/ 4 | /features/ 5 | -------------------------------------------------------------------------------- /jsonedit-site/category.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | This is the update site for JSON Editor 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /jsonedit-site/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | JSON Editor Update Site 5 | 6 | 7 | 8 | 9 |

10 |

Loading ...

11 |
12 | 13 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /jsonedit-site/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | 7 | com.boothen 8 | jsonedit-parent 9 | 1.1.3 10 | 11 | 12 | jsonedit-repository 13 | eclipse-repository 14 | 15 | 16 | 17 | 18 | org.eclipse.tycho 19 | tycho-p2-repository-plugin 20 | ${tycho.version} 21 | 22 | false 23 | false 24 | eclipse-json-editor 25 | 26 | 27 | 28 | org.eclipse.tycho 29 | tycho-p2-director-plugin 30 | ${tycho.version} 31 | 32 | 33 | materialize-products 34 | 35 | materialize-products 36 | 37 | 38 | 39 | archive-products 40 | 41 | archive-products 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /jsonedit-site/scripts/m-xml.min.js: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Magic XML by Tom Davies 3 | ----------------------- 4 | Magically implements cross-browser code from w3schools.com/xsl/xsl_client.asp 5 | to pull in XML data and apply a specified XSLT on marked up elements. 6 | 7 | More details at: http://tomdavies.azurewebsites.net/magicxml/ 8 | 9 | ******************************************************************************/ 10 | /* 11 | The MIT License (MIT) 12 | 13 | Copyright (C) 2013 - Tom Davies (tom@t-davies.com) 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy 16 | of this software and associated documentation files (the "Software"), to deal 17 | in the Software without restriction, including without limitation the rights 18 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 19 | copies of the Software, and to permit persons to whom the Software is 20 | furnished to do so, subject to the following conditions: 21 | 22 | The above copyright notice and this permission notice shall be included in 23 | all copies or substantial portions of the Software. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 31 | THE SOFTWARE. 32 | */ 33 | +function(e,t,r){function n(e){return e.indexOf('=0}function a(t){var r=e.ActiveXObject||"ActiveXObject"in e?new ActiveXObject("Msxml2.XMLHTTP.3.0"):new XMLHttpRequest;return r.open("GET",t,!1),r.send(),r.responseXML}function i(e){return v.xmlStringParser.parse(e)}function c(){var t=function(){console.error("[Magic XML] No XML string parser available.")};return e.DOMParser?t=function(t){var r=new e.DOMParser;return r.parseFromString(t,"text/xml")}:e.ActiveXObject||"ActiveXObject"in e?t=function(e){var t=new ActiveXObject("Microsoft.XMLDOM");return t.async=!1,t.loadXML(e),t}:console.warn("[Magic XML] No XML string parser available. String parsing will fail if used."),{parse:t}}function o(t){if(e.ActiveXObject||"ActiveXObject"in e){var r=new ActiveXObject("MSXML2.FreeThreadedDOMDocument.6.0");return r.async=!1,r.load(t),r}return a(t)}function s(e,n,a){var i,c=0,o=new XSLTProcessor;if(o.importStylesheet(n),a!==r)for(c;c 2 | 3 | 4 | This is the update site for JSON Editor 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /jsonedit-site/sync_with_folder.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [[ -z "$1" ]] ; then 4 | echo 'Please specify the path to target folder' 5 | exit 0 6 | fi 7 | 8 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 9 | SITE=$SCRIPT_DIR 10 | TARGET=$1 11 | 12 | echo "Copying p2 update site content.." 13 | cp -v -r $SITE/*.jar $SITE/site.xml $SITE/features $SITE/plugins $TARGET 14 | 15 | echo "Copying website content.." 16 | cp -v -r $SITE/web $SITE/index.html $SITE/scripts $TARGET 17 | 18 | 19 | -------------------------------------------------------------------------------- /jsonedit-site/sync_with_website.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 3 | SITE=$SCRIPT_DIR 4 | TARGET="martin-steiger.de:/var/www/html/jsonedit" 5 | 6 | echo "Copying p2 update site content.." 7 | scp -p -r $SITE/*.jar $SITE/site.xml $SITE/features $SITE/plugins $TARGET 8 | 9 | echo "Copying website content.." 10 | scp -p -r $SITE/web $SITE/index.html $SITE/scripts $TARGET 11 | 12 | # read -r raw input - disables interpretion of backslash escapes and line-continuation in the read data 13 | # read -p the prompt string is output 14 | # read -s to hide typed chars 15 | 16 | read -r -p "Press [ENTER] to exit..." 17 | 18 | 19 | -------------------------------------------------------------------------------- /jsonedit-site/web/site.css: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /jsonedit-test/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Bundle-ManifestVersion: 2 3 | Bundle-Name: JSON Editor Plugin Test Fragment 4 | Bundle-SymbolicName: jsonedit-test 5 | Bundle-Version: 1.1.3 6 | Fragment-Host: jsonedit-core 7 | Bundle-RequiredExecutionEnvironment: JavaSE-1.7 8 | Require-Bundle: org.junit, 9 | jsonedit-model, 10 | ch.qos.logback.core, 11 | org.antlr.antlr4-runtime 12 | -------------------------------------------------------------------------------- /jsonedit-test/build.properties: -------------------------------------------------------------------------------- 1 | source.. = src/main/java, src/main/resources 2 | output.. = target/classes 3 | bin.includes = META-INF/,\ 4 | . 5 | -------------------------------------------------------------------------------- /jsonedit-test/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | 7 | com.boothen 8 | jsonedit-parent 9 | 1.1.3 10 | 11 | 12 | jsonedit-test 13 | eclipse-test-plugin 14 | 15 | 16 | 17 | 18 | 19 | org.eclipse.tycho 20 | tycho-surefire-plugin 21 | ${tycho.version} 22 | 23 | false 24 | false 25 | 26 | **/TestErrorReporter.java 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /jsonedit-test/src/main/java/com/boothen/jsonedit/core/ParseTreeSerializer.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.core; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | import org.antlr.v4.runtime.tree.ParseTree; 8 | import org.antlr.v4.runtime.tree.TerminalNode; 9 | import org.eclipse.jface.text.Position; 10 | 11 | /** 12 | * Converts a {@link ParseTree} to a list of text strings. 13 | */ 14 | public class ParseTreeSerializer { 15 | 16 | public static void comp(ParseTree syntaxTree, Map positions, 17 | ParseTree oldRoot, Map oldPositions) { 18 | List newTreeText = ParseTreeSerializer.toString(syntaxTree, positions); 19 | List oldTreeText = ParseTreeSerializer.toString(oldRoot, oldPositions); 20 | for (int i = 0; i < Math.max(newTreeText.size(), oldTreeText.size()); i++) { 21 | String left = (i < newTreeText.size()) ? newTreeText.get(i) : ""; 22 | String right = (i < oldTreeText.size()) ? oldTreeText.get(i) : ""; 23 | String both = String.format("%-60.60s | %-60.60s", left, right); 24 | System.out.println(both); 25 | } 26 | } 27 | 28 | public static List toString(ParseTree syntaxTree, Map positions) { 29 | List list = new ArrayList<>(); 30 | toString(list, syntaxTree, positions, 0); 31 | return list; 32 | } 33 | 34 | private static void toString(List list, ParseTree tree, Map positions, int level) { 35 | 36 | String name = tree.getClass().getSimpleName(); 37 | if (tree instanceof TerminalNode) { 38 | name = "'" + ((TerminalNode)tree).getText() + "'"; 39 | } 40 | Position pos = positions.get(tree); 41 | 42 | String text = ""; 43 | for (int i = 0; i < level; i++) { 44 | text += " "; 45 | } 46 | text += String.format("(%s) -> %s", pos, name); 47 | list.add(text); 48 | 49 | for (int i = 0; i < tree.getChildCount(); i++) { 50 | ParseTree child= tree.getChild(i); 51 | toString(list, child, positions, level + 1); 52 | } 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /jsonedit-test/src/main/java/com/boothen/jsonedit/core/util/FileToDocUtility.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.core.util; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.File; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.io.InputStreamReader; 8 | import java.net.URI; 9 | import java.net.URISyntaxException; 10 | import java.net.URL; 11 | 12 | import org.eclipse.core.runtime.FileLocator; 13 | import org.eclipse.jface.text.Document; 14 | import org.eclipse.jface.text.IDocument; 15 | 16 | public class FileToDocUtility { 17 | 18 | public static IDocument getDocument(String location) { 19 | 20 | try { 21 | InputStream is = FileToDocUtility.class.getResourceAsStream("/" + location); 22 | 23 | return new Document(readStreamAsString(is)); 24 | } catch (IOException e) { 25 | e.printStackTrace(); 26 | } 27 | 28 | return null; 29 | } 30 | 31 | public static File getFile(String file) { 32 | 33 | try { 34 | URL resource = FileToDocUtility.class.getResource("/" + file); 35 | URI uri = null; 36 | if (resource.toString().startsWith("bundleresource")) { 37 | uri =FileLocator.toFileURL(resource).toURI(); 38 | } else { 39 | uri =resource.toURI(); 40 | } 41 | return new File(uri); 42 | } catch (URISyntaxException e) { 43 | e.printStackTrace(); 44 | } catch (IOException e) { 45 | e.printStackTrace(); 46 | } 47 | return null; 48 | } 49 | 50 | private static String readStreamAsString(InputStream is) 51 | throws java.io.IOException{ 52 | StringBuilder fileData = new StringBuilder(1000); 53 | BufferedReader reader = new BufferedReader( 54 | new InputStreamReader(is)); 55 | char[] buf = new char[1024]; 56 | int numRead=0; 57 | while((numRead=reader.read(buf)) != -1){ 58 | String readData = String.valueOf(buf, 0, numRead); 59 | fileData.append(readData); 60 | buf = new char[1024]; 61 | } 62 | reader.close(); 63 | return fileData.toString(); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/array.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "key":"value", 4 | "key":1.1e-3, 5 | "key":null, 6 | "key":true, 7 | "key":false, 8 | "key": { 9 | "key":"value" 10 | }, 11 | "key": [ 1.1e-3, "value", null, true, false] 12 | 13 | }, 14 | 1.1e-3, 15 | "value", 16 | null, 17 | true, 18 | false 19 | ] -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/getMediaDetails_null_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "version":{ 3 | "entry":123808284642, 4 | "search":123808284642, 5 | "tag":123808284642, 6 | "notification":123808284642, 7 | "offeredshare":123808284642, 8 | "receivedshare":123808284642, 9 | "user":123808284642, 10 | "quota":123808284642 11 | }, 12 | "message":"success", 13 | "code":-1, 14 | "response":null 15 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/object.json: -------------------------------------------------------------------------------- 1 | { 2 | "key":"value", 3 | "key":1.1e-3, 4 | "key":null, 5 | "key":true, 6 | "key":false, 7 | "key": { 8 | "key":"value" 9 | }, 10 | "key": [ 1.1e-3, "value", null, true, false] 11 | 12 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "glossary": { 3 | "title": "example glossary", 4 | "GlossDiv": { 5 | "title": "S", 6 | "val": -1.0e1113, 7 | "GlossList": { 8 | "GlossEntry": { 9 | "ID": "SGML", 10 | "SortAs": "SGML", 11 | "GlossTerm": "Standard Generalized Markup Language", 12 | "Acronym": "SGM", 13 | "Acronym": "SGML2", 14 | "Abbrev": "ISO 8879:1986", 15 | "GlossDef": { 16 | "para": "A meta-markup\\ lan\"guage,\\\asab\ab\\s\qq\u u\s\"ed to \n re\kate \u89mark\u23a41p languges s\\uch as Do,cBook.\\a", 17 | "GlossSeeAlso": ["GML", "XML"] 18 | }, 19 | "GlossSee": "markup" 20 | } 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test1.json: -------------------------------------------------------------------------------- 1 | {"version":{"entry":123808284642,"search":123808284642,"tag":123808284642,"notification":123808284642,"offeredshare":123808284642,"receivedshare":123808284642,"user":123808284642,"quota":123808284642},"message":"success","code":-1,"response":null} -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test12.json: -------------------------------------------------------------------------------- 1 | { 2 | garbage 3 | "afsda", 4 | "2009-02-17 10:07:47", 5 | "ultime":"2009-12-17 11:17:57", 6 | garbage 7 | "ctime":"2009-22-17 12:27:67" 8 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test13.json: -------------------------------------------------------------------------------- 1 | { 2 | "dlsTrace":"#0 \/var\/www\/lib\/Dls\/Rest\/Server.php(83): Dls_Rest_Server->_getMethodParams(Object(Dls_Service_Rest_Entry), 'getPhotosOfAlbu...', Array)\n#1 \/var\/www\/service\/index.php(54): Dls_Rest_Server->handle()\n#2 {main}" 3 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test14.json: -------------------------------------------------------------------------------- 1 | { 2 | "t:est":"test", 3 | "test":"test" 4 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test15.json: -------------------------------------------------------------------------------- 1 | { 2 | "dlsTrace":"#0 \/var\/www\/lib\/Dls\/Rest\/Server.php(83): Dls_Rest_Server->_getMethodParams(Object(Dls_Service_Rest_Entry), 'getPhotosOfAlbu...', Array)\n#1 \/var\/www\/service\/index.php(54): Dls_Rest_Server->handle()\n#2 {main}", 3 | "test":"test" 4 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test16.json: -------------------------------------------------------------------------------- 1 | { 2 | "t:est":"test" 3 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test17.json: -------------------------------------------------------------------------------- 1 | { 2 | " 3 | "test2":"test" 4 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test18.json: -------------------------------------------------------------------------------- 1 | { 2 | "asd 3 | "test2":"test" 4 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test19.json: -------------------------------------------------------------------------------- 1 | { 2 | "test":[ 3 | 4 | ] 5 | 6 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test2.json: -------------------------------------------------------------------------------- 1 | { 2 | "response":{ 3 | "id":"232", 4 | "parent_id":"13", 5 | "idpath":"\/11\/13\/1141\/", 6 | "representations":{ 7 | "16x16.jpg":"FINISHED", 8 | "54x41.jpg":"FINISHED", 9 | "76x81.jpg":"FINISHED", 10 | "mobil54x41.jpg":"FINISHED", 11 | "mobil76x81.jpg":"FINISHED", 12 | "mobil450x450.jpg":"FINISHED", 13 | "120x150.jpg":"FINISHED", 14 | "450x450.jpg":"FINISHED", 15 | "800x800.jpg":"FINISHED", 16 | "exif":"FINISHED", 17 | "iptc":"FINISHED", 18 | "xmp":"FINISHED", 19 | "iptv174x174.png":"FINISHED", 20 | "iptv640x480.png":"FINISHED", 21 | "iptv854x480.png":"FINISHED" 22 | }, 23 | "properties":{ 24 | "EXIF":{ 25 | "FileName":"726.jpg", 26 | "FileDateTime":"1234861650", 27 | "FileSize":"31956", 28 | "FileType":"2", 29 | "MimeType":"image\/jpeg", 30 | "COMPUTED":{ 31 | "html":"width=\"300\" height=\"420\"", 32 | "Height":"420", 33 | "Width":"300", 34 | "IsColor":"1" 35 | }, 36 | "Company":"Ducky" 37 | } 38 | }, 39 | "visible":"1", 40 | "encrypted":"0", 41 | "file_type":null, 42 | "purchased":"0", 43 | "ultime":"2009-02-17 10:07:47", 44 | "ctime":"2009-02-17 10:07:47", 45 | "metadata":null, 46 | "favourite":"0" 47 | } 48 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test20.json: -------------------------------------------------------------------------------- 1 | { 2 | "asd" 3 | "test2":"test" 4 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test21.json: -------------------------------------------------------------------------------- 1 | { 2 | "test": { 3 | 4 | }, 5 | "test":"test" 6 | 7 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test22.json: -------------------------------------------------------------------------------- 1 | { 2 | "test": { 3 | "asd" 4 | }, 5 | "test":"test" 6 | 7 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test23.json: -------------------------------------------------------------------------------- 1 | { 2 | "asd":"a 3 | "test":{ 4 | "test":"test" 5 | }, 6 | "test":123 7 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test24.json: -------------------------------------------------------------------------------- 1 | { 2 | "t:est":"test", 3 | "te:st":"test", 4 | "te:st":"test" 5 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test25.json: -------------------------------------------------------------------------------- 1 | { 2 | "t:est":"" 3 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test26.json: -------------------------------------------------------------------------------- 1 | { 2 | "array":[ 3 | [ 4 | { 5 | "mdate":"2009-02-10 16:01:54" 6 | } 7 | ], 8 | [ 9 | { 10 | "mdate":"2009-02-10 16:01:54" 11 | } 12 | ] 13 | ] 14 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test27.json: -------------------------------------------------------------------------------- 1 | { 2 | "object":{ 3 | "array":[ 4 | "asdf:asd" 5 | ] 6 | } 7 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test28.json: -------------------------------------------------------------------------------- 1 | { 2 | "object":{ 3 | "object2":{ 4 | "asdf:asd":"asd:asd" 5 | }, 6 | "string1":"strgin" 7 | } 8 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test29.json: -------------------------------------------------------------------------------- 1 | { 2 | "obj:ect":{ 3 | "array":[ 4 | "asdfasd" 5 | ] 6 | } 7 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test3.json: -------------------------------------------------------------------------------- 1 | { 2 | "message":"success", 3 | "code":-1, 4 | "response":{ 5 | "84":{ 6 | "meta":{ 7 | "id":"84", 8 | "parent_id":"2", 9 | "idpath":"\/2\/84\/", 10 | "user_id":"1", 11 | "entry_type":"space", 12 | "storage_id":null, 13 | "entry_subtype":"DEFAULT", 14 | "access_type":"PUBLIC", 15 | "name":"Bens Share", 16 | "mtime":"2008-12-17 13:44:36", 17 | "favourite":"0", 18 | "hash":null, 19 | "size":null, 20 | "physical_path":null, 21 | "mime_type":null, 22 | "ref_count":null, 23 | "quarantine_path":null, 24 | "representations":false, 25 | "properties":null, 26 | "visible":null, 27 | "encrypted":null, 28 | "file_type":null, 29 | "purchased":null, 30 | "ultime":"2008-12-17 13:44:36", 31 | "ctime":"2008-12-17 13:44:36", 32 | "metadata":null, 33 | "files":3, 34 | "folders":0, 35 | "projects":0, 36 | "shares":[ 37 | { 38 | "user_id":"1", 39 | "id":"84", 40 | "parent_id":"2", 41 | "name":"Bens Share", 42 | "entry_subtype":"DEFAULT", 43 | "access_type":"PUBLIC", 44 | "ctime":"2008-12-17 13:44:36", 45 | "metadata":null, 46 | "friend_id":"1", 47 | "folder_id":"84", 48 | "rights":"2", 49 | "start_date":null, 50 | "end_date":"0000-00-00", 51 | "path":"\/2\/84\/", 52 | "firstname":"Tom", 53 | "secondname":"Ate", 54 | "email":"postfach@imur.eu" 55 | } 56 | ], 57 | "entries":[ 58 | 59 | ] 60 | }, 61 | "id":"84" 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test30.json: -------------------------------------------------------------------------------- 1 | { 2 | "obj:ect":123 3 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test31.json: -------------------------------------------------------------------------------- 1 | { 2 | "object":{ 3 | "object2":{ 4 | "asdf:asd":true 5 | }, 6 | "string1":"strgin" 7 | } 8 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test32.json: -------------------------------------------------------------------------------- 1 | { 2 | "object":{ 3 | "object2":{ 4 | "asdf:asd":null 5 | }, 6 | "string1":"strgin" 7 | } 8 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test33.json: -------------------------------------------------------------------------------- 1 | { 2 | "object":"{}" 3 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test34.json: -------------------------------------------------------------------------------- 1 | { 2 | "object":"{t}" 3 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test35.json: -------------------------------------------------------------------------------- 1 | [ 2 | "object","[]" 3 | ] -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test36.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test37.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "productCatalogId":3478 4 | , 5 | { 6 | "productCatalogId":39 7 | } 8 | ] -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test38.json: -------------------------------------------------------------------------------- 1 | { 2 | "asdas":{ 3 | "productCatalogId":3478 4 | , 5 | "errorBefore":{ 6 | "prod":12312 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test39.json: -------------------------------------------------------------------------------- 1 | [ 2 | "1,2,34" 3 | ] -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test4.json: -------------------------------------------------------------------------------- 1 | { 2 | "message":"success", 3 | "code":-1, 4 | "response":{ 5 | "84":{ 6 | "meta":{ 7 | "purchased":null, 8 | "entries":[ 9 | 12312312, 12312312, 123123123, 1231231 10 | ], 11 | "entries2":[ 12 | "12312312", "12312312", "123123123", "1231231" 13 | ], 14 | "entries3":[ 15 | true, false, true, null 16 | ] 17 | }, 18 | "id":"84" 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test40.json: -------------------------------------------------------------------------------- 1 | { 2 | "asd":["a","b","c"} 3 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test41.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | "asd":[]} 4 | 5 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test42.json: -------------------------------------------------------------------------------- 1 | ["a"} -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test43.json: -------------------------------------------------------------------------------- 1 | { 2 | "asdas":"asdas", 3 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test44.json: -------------------------------------------------------------------------------- 1 | [ 2 | "asdas", 3 | 1, 4 | ] -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test45.json: -------------------------------------------------------------------------------- 1 | { 2 | "asdas":[ 3 | "asda", 4 | ] 5 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test46.json: -------------------------------------------------------------------------------- 1 | { 2 | "asdas":"asdas", 3 | "asdas":"asdas", 4 | "aadsas:null 5 | -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test47.json: -------------------------------------------------------------------------------- 1 | [ 2 | "asdas",1,"asda" -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test48.json: -------------------------------------------------------------------------------- 1 | { 2 | "asdasd": { 3 | "asdas": { 4 | 5 | }, 6 | "asdas": { 7 | 8 | } 9 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test49.json: -------------------------------------------------------------------------------- 1 | { 2 | "helalo":"soa", 3 | "asdaa":"aasda", 4 | "asdas":"adasd", 5 | "asdas":{ 6 | "asdas":true, 7 | "asda":3.12, 8 | "asdas":false, 9 | "asda":null, 10 | "asdas":"asdas", 11 | "asdas":12312 12 | }, 13 | "aassdaas":[ 14 | "asdasd", 15 | 12312, 16 | -12.23, 17 | null, 18 | false, 19 | true 20 | ], 21 | "aassdaas":[ 22 | 23 | ], 24 | "asdasda":{ 25 | 26 | }, 27 | "sdas":"dave", 28 | "asdas":"asd" 29 | } 30 | 31 | { 32 | "helalo":"soa", 33 | "asdaa":"aasda", 34 | "asdas":"adasd", 35 | "asdas":{ 36 | "asdas":true, 37 | "asda":3.12, 38 | "asdas":false, 39 | "asda":null, 40 | "asdas":"asdas", 41 | "asdas":12312 42 | }, 43 | "aassdaas":[ 44 | "asdasd", 45 | 12312, 46 | -12.23, 47 | null, 48 | false, 49 | true 50 | ], 51 | "aassdaas":[ 52 | 53 | ], 54 | "asdasda":{ 55 | 56 | }, 57 | "sdas":"dave", 58 | "asdas":"asd" 59 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test5.json: -------------------------------------------------------------------------------- 1 | { 2 | "hell 3 | 4 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test6.json: -------------------------------------------------------------------------------- 1 | { 2 | "hell":" 3 | 4 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test7.json: -------------------------------------------------------------------------------- 1 | { 2 | "hell":"asf", 3 | dsfsdaf 4 | 5 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test8.json: -------------------------------------------------------------------------------- 1 | { 2 | "hell":234234 { 3 | 4 | } -------------------------------------------------------------------------------- /jsonedit-test/src/main/resources/test9.json: -------------------------------------------------------------------------------- 1 | [ 2 | "hell", 3 | "hell", 4 | { 5 | "aasd":"asd" 6 | }, 7 | 1231 8 | ] -------------------------------------------------------------------------------- /jsonedit-test/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "glossary": { 3 | "title": "example glossary", 4 | "GlossDiv": { 5 | "title": "S", 6 | "GlossList": { 7 | "GlossEntry": { 8 | "ID": "SGML", 9 | "SortAs": "SGML", 10 | "GlossTerm": "Standard Generalized Markup Language", 11 | "Acronym": "SGML", 12 | "Abbrev": "ISO 8879:1986", 13 | "GlossDef": { 14 | "para": "A meta-markup language, used to create markup languages such as DocBook.", 15 | "GlossSeeAlso": ["GML", "XML"] 16 | }, 17 | "GlossSee": "markup" 18 | } 19 | } 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /jsonedit-text/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Bundle-ManifestVersion: 2 3 | Bundle-Name: JSON Editor Text 4 | Bundle-SymbolicName: jsonedit-text 5 | Bundle-Version: 1.1.3 6 | Bundle-RequiredExecutionEnvironment: JavaSE-1.7 7 | Bundle-Vendor: Boothen Technology 8 | Require-Bundle: org.eclipse.core.resources, 9 | org.eclipse.core.runtime, 10 | org.eclipse.jface.text, 11 | org.eclipse.ui, 12 | jsonedit-model, 13 | jsonedit-core, 14 | org.antlr.antlr4-runtime 15 | Import-Package: com.boothen.jsonedit.core 16 | Export-Package: com.boothen.jsonedit.text 17 | -------------------------------------------------------------------------------- /jsonedit-text/build.properties: -------------------------------------------------------------------------------- 1 | source.. = src/main/java 2 | output.. = target/classes 3 | bin.includes = META-INF/,\ 4 | . 5 | -------------------------------------------------------------------------------- /jsonedit-text/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | 7 | com.boothen 8 | jsonedit-parent 9 | 1.1.3 10 | 11 | 12 | jsonedit-text 13 | eclipse-plugin 14 | 15 | 16 | -------------------------------------------------------------------------------- /jsonedit-text/src/main/java/com/boothen/jsonedit/text/PositionVisitor.java: -------------------------------------------------------------------------------- 1 | package com.boothen.jsonedit.text; 2 | 3 | import java.util.LinkedHashMap; 4 | 5 | import org.antlr.v4.runtime.ParserRuleContext; 6 | import org.antlr.v4.runtime.Token; 7 | import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; 8 | import org.antlr.v4.runtime.tree.ErrorNode; 9 | import org.antlr.v4.runtime.tree.ParseTree; 10 | import org.antlr.v4.runtime.tree.RuleNode; 11 | import org.antlr.v4.runtime.tree.TerminalNode; 12 | import org.eclipse.jface.text.Position; 13 | 14 | /** 15 | * Creates {@link Position} instances that wrap around every node in the syntax tree. 16 | * Explicitly returns a {@link LinkedHashMap} to indicate that elements are ordered as they 17 | * are encountered by depth first traversal. 18 | */ 19 | public class PositionVisitor extends AbstractParseTreeVisitor> { 20 | 21 | private final LinkedHashMap positions = new LinkedHashMap<>(); 22 | 23 | @Override 24 | public LinkedHashMap visitChildren(RuleNode node) { 25 | ParserRuleContext ctx = (ParserRuleContext) node; 26 | 27 | // Add successful rule matches only 28 | // TODO: maybe just skip over this element on exceptions and try to add children 29 | if (ctx.exception == null) { 30 | positions.put(node, createPosition(ctx.start, ctx.stop)); 31 | 32 | for (int i=0; i visitTerminal(TerminalNode node) { 42 | Token symbol = node.getSymbol(); 43 | positions.put(node, createPosition(symbol, symbol)); 44 | return positions; 45 | } 46 | 47 | @Override 48 | public LinkedHashMap visitErrorNode(ErrorNode node) { 49 | // ignore error tokens - they have invalid positions 50 | return positions; 51 | } 52 | 53 | private Position createPosition(Token start, Token stop) { 54 | int startIndex = start.getStartIndex(); 55 | // stop token is null if the whole tree is just EOF (document out of sync) 56 | int stopIndex = stop != null ? stop.getStopIndex() : startIndex - 1; 57 | Position pos = new Position(startIndex, stopIndex - startIndex + 1); 58 | return pos; 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /org.sourceforge.jsonedit.core/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /org.sourceforge.jsonedit.core/src/org/sourceforge/jsonedit/core/prefs/PreferenceInitializer.java: -------------------------------------------------------------------------------- 1 | package org.sourceforge.jsonedit.core.prefs; 2 | 3 | import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; 4 | import org.eclipse.jface.preference.IPreferenceStore; 5 | import org.eclipse.jface.preference.PreferenceConverter; 6 | import org.eclipse.swt.graphics.Color; 7 | import org.eclipse.swt.graphics.RGB; 8 | import org.eclipse.swt.widgets.Display; 9 | import org.sourceforge.jsonedit.core.JsonEditorPlugin; 10 | import org.sourceforge.jsonedit.core.util.JsonColorProvider; 11 | 12 | public class PreferenceInitializer extends AbstractPreferenceInitializer { 13 | 14 | @Override 15 | public void initializeDefaultPreferences() { 16 | 17 | IPreferenceStore store = JsonEditorPlugin.getJsonPreferenceStore(); 18 | PreferenceConverter.setDefault(store, JsonColorProvider.STRING, new RGB(0, 128, 0)); 19 | PreferenceConverter.setDefault(store, JsonColorProvider.DEFAULT, new RGB(0, 0, 0)); 20 | PreferenceConverter.setDefault(store, JsonColorProvider.VALUE, new RGB(0, 0, 128)); 21 | PreferenceConverter.setDefault(store, JsonColorProvider.NULL, new RGB(128, 0, 128)); 22 | 23 | store.setDefault(JsonEditorPlugin.SPACES_FOR_TABS, true); 24 | store.setDefault(JsonEditorPlugin.NUM_SPACES, 4); 25 | store.setDefault(JsonEditorPlugin.EDITOR_MATCHING_BRACKETS, true); 26 | 27 | store.setDefault(JsonEditorPlugin.EDITOR_MATCHING_BRACKETS_COLOR, new Color(Display.getCurrent(), new RGB(0, 128, 0)).toString()); 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /org.sourceforge.jsonedit.feature/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /org.sourceforge.jsonedit.test/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | com.boothen 6 | jsonedit-parent 7 | 1.1.3 8 | pom 9 | 10 | jsonedit-core 11 | jsonedit-feature 12 | jsonedit-editor 13 | jsonedit-folding 14 | jsonedit-model 15 | jsonedit-outline 16 | jsonedit-preferences 17 | jsonedit-site 18 | jsonedit-test 19 | jsonedit-text 20 | 21 | 22 | 23 | UTF-8 24 | 1.1.0 25 | 1.3 26 | 4.10 27 | 1.9.0 28 | 29 | 30 | 31 | 32 | indigo 33 | p2 34 | http://download.eclipse.org/releases/indigo 35 | 36 | 37 | antlr 38 | p2 39 | http://martin-steiger.de/antlr47 40 | 41 | 42 | 43 | 44 | 45 | 46 | org.eclipse.tycho 47 | tycho-maven-plugin 48 | ${tycho.version} 49 | true 50 | 51 | 52 | org.eclipse.tycho 53 | target-platform-configuration 54 | ${tycho.version} 55 | 56 | 57 | 58 | win32 59 | win32 60 | x86 61 | 62 | 63 | win32 64 | win32 65 | x86_64 66 | 67 | 68 | linux 69 | gtk 70 | x86 71 | 72 | 73 | linux 74 | gtk 75 | x86_64 76 | 77 | 78 | macosx 79 | cocoa 80 | x86_64 81 | 82 | 83 | 84 | 85 | 86 | org.eclipse.tycho 87 | tycho-compiler-plugin 88 | ${tycho.version} 89 | 90 | 1.7 91 | 1.7 92 | 93 | -warn:+discouraged,forbidden 94 | 95 | 96 | 97 | org.eclipse.tycho 98 | tycho-packaging-plugin 99 | ${tycho.version} 100 | 101 | '${build.qualifier}' 102 | 103 | 104 | 105 | org.eclipse.tycho 106 | tycho-versions-plugin 107 | ${tycho.version} 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /release-process.md: -------------------------------------------------------------------------------- 1 | # Update version number 2 | 3 | To upgrade the version, quite a few things need to be adjusted. 4 | 5 | ### Update all Maven files: 6 | 7 | The following snippet updates the version entry in all pom.xml files: 8 | 9 | ```bash 10 | mvn versions:set -DnewVersion=1.0.0.final -DgenerateBackupPoms=false 11 | ``` 12 | 13 | or 14 | 15 | ```bash 16 | mvn versions:set -DnewVersion=1.0.0.final 17 | mvn versions:commit 18 | ``` 19 | 20 | ### Eclipse manifest files 21 | 22 | **Note:** I suspect that there is an easier way, probably through Tycho: 23 | auto-generate eclipse files or use mvn install directly to build the target site? 24 | 25 | * Manually open and edit the version entry in the different plugins (including the test bundle fragment). 26 | * Open and adjust the version in the `feature.xml` file 27 | * Open the `site.xml` and edit the XML content directly: add a new entry for the new version. 28 | Go back to "Site Map" and build only the new feature - the older ones are unresolvable. 29 | 30 | * Update the "category.xml" file: the jar file path and the feature version must be updated 31 | 32 | 33 | # Update Site 34 | 35 | * Copy the relevant files to the root folder in the `gh-pages` branch. 36 | Easiest to do with the branch checked out in a separate folder. 37 | * Add all files to the git index and compare with that last commit: `git whatchanged -1` 38 | It should look identical. 39 | 40 | * Create a commit and push it. 41 | * Verify with a new (minimal) installation of eclipse: 42 | http://download.eclipse.org/eclipse/downloads/ 43 | (Select a version and download *Platform Runtime Binary*) - it does not contain the Marketplace plugin though (MPC). 44 | * Download and installation process should work fine 45 | 46 | # Marketplace 47 | 48 | Go to https://marketplace.eclipse.org/content/json-editor-plugin and add a new version feature. 49 | It might not show up instantly in Marketplace, but it should work. 50 | 51 | --------------------------------------------------------------------------------