├── .gitignore ├── nbproject ├── .DS_Store ├── project.properties ├── genfiles.properties ├── platform.properties ├── build-impl.xml └── project.xml ├── release └── modules │ └── ext │ └── gson-2.2.2.jar ├── src └── net │ └── dfranek │ └── typoscript │ ├── resources │ ├── ts.png │ ├── type.png │ ├── logic.png │ ├── menus.png │ ├── value.png │ ├── wraps.png │ ├── constants.png │ ├── content.png │ ├── effects.png │ ├── parsing.png │ ├── ts_file_16.png │ ├── templates │ │ ├── TSTemplate.ts │ │ ├── TSTemplateComments.ts │ │ ├── TSTemplate.html │ │ ├── TSTemplateHTML5Advanced.html │ │ ├── TSTemplateRTE.html │ │ ├── TSTemplateComments.html │ │ ├── TSTemplateHTML5Multilingual.html │ │ ├── TSTemplateHTML5Advanced.ts │ │ ├── TSTemplateHTML5Multilingual.ts │ │ └── TSTemplateRTE.ts │ ├── TSExample.ts │ ├── Bundle.properties │ ├── FontAndColors.xml │ ├── layer.xml │ └── TSResolver.xml │ ├── Bundle.properties │ ├── parser │ ├── TSParserResult.java │ ├── TSBracketNode.java │ ├── TSError.java │ ├── TSParser.java │ ├── ast │ │ ├── TSASTNode.java │ │ └── TSASTNodeType.java │ ├── TSParserUtils.java │ └── TSTokenParser.java │ ├── lexer │ ├── TSLexerState.java │ ├── TSLanguageHierarchy.java │ ├── TSLexer.java │ ├── TSTokenId.java │ └── TSLexerUtils.java │ ├── indent │ ├── TSBracesMatcherFactory.java │ └── TSBracesMatcher.java │ ├── completion │ ├── tsref │ │ ├── TSRefProperty.java │ │ ├── TSRefType.java │ │ └── TSRef.java │ ├── TSCompletionResult.java │ ├── TSElement.java │ └── TSCompletionItem.java │ ├── embedding │ └── HtmlEmbeddingProvider.java │ ├── nav │ └── TSDeclarationFinder.java │ ├── typinghooks │ ├── TSTypedTextInterceptor.java │ └── TSTypedBreakInterceptor.java │ └── TSLanguage.java ├── test └── unit │ └── src │ └── net │ └── dfranek │ └── typoscript │ ├── lexer │ ├── Test.ts │ ├── TSExample │ ├── TSLexerTestUtils.java │ └── TSScannerTest.java │ └── parser │ ├── test.ts │ ├── TSParserTestUtils.java │ └── TSTokenParserTest.java ├── manifest.mf ├── README ├── helper └── json.php └── CHANGELOG /.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /nbproject/private/ 3 | .DS_Store 4 | /local/ -------------------------------------------------------------------------------- /nbproject/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfranek/NetBeans-TypoScript/HEAD/nbproject/.DS_Store -------------------------------------------------------------------------------- /release/modules/ext/gson-2.2.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfranek/NetBeans-TypoScript/HEAD/release/modules/ext/gson-2.2.2.jar -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/ts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfranek/NetBeans-TypoScript/HEAD/src/net/dfranek/typoscript/resources/ts.png -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/type.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfranek/NetBeans-TypoScript/HEAD/src/net/dfranek/typoscript/resources/type.png -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/logic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfranek/NetBeans-TypoScript/HEAD/src/net/dfranek/typoscript/resources/logic.png -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/menus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfranek/NetBeans-TypoScript/HEAD/src/net/dfranek/typoscript/resources/menus.png -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/value.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfranek/NetBeans-TypoScript/HEAD/src/net/dfranek/typoscript/resources/value.png -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/wraps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfranek/NetBeans-TypoScript/HEAD/src/net/dfranek/typoscript/resources/wraps.png -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/constants.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfranek/NetBeans-TypoScript/HEAD/src/net/dfranek/typoscript/resources/constants.png -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/content.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfranek/NetBeans-TypoScript/HEAD/src/net/dfranek/typoscript/resources/content.png -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/effects.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfranek/NetBeans-TypoScript/HEAD/src/net/dfranek/typoscript/resources/effects.png -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/parsing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfranek/NetBeans-TypoScript/HEAD/src/net/dfranek/typoscript/resources/parsing.png -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/ts_file_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfranek/NetBeans-TypoScript/HEAD/src/net/dfranek/typoscript/resources/ts_file_16.png -------------------------------------------------------------------------------- /test/unit/src/net/dfranek/typoscript/lexer/Test.ts: -------------------------------------------------------------------------------- 1 | {} 2 | ( 3 | 4 | 5 | ) 6 | [] 7 | [browser = msie] { AND } [ version > 5] 8 | { 9 | ( 10 | ) 11 | } 12 | ( 13 | ) 14 | {} 15 | {} 16 | ] -------------------------------------------------------------------------------- /test/unit/src/net/dfranek/typoscript/lexer/TSExample: -------------------------------------------------------------------------------- 1 | headerimg.file { 2 | XY = [10.w]+2,20 3 | } 4 | 5 | [globalVar=TSFE:type = 0] 6 | page.typeNum = 0 7 | [global] 8 | 9 | page.10.value ( 10 | Multi 11 | Line 12 | Value 13 | ) -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/templates/TSTemplate.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Project: ${project.displayName} - ${project.name} 3 | * Version: 1.0.0 4 | * Date: ${date} ${time} 5 | * Author: ${user} 6 | * 7 | * Coded with Netbeans! 8 | */ 9 | -------------------------------------------------------------------------------- /manifest.mf: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | OpenIDE-Module: net.dfranek.typoscript/1 3 | OpenIDE-Module-Implementation-Version: 0 4 | OpenIDE-Module-Layer: net/dfranek/typoscript/resources/layer.xml 5 | OpenIDE-Module-Localizing-Bundle: net/dfranek/typoscript/resources/Bundle.properties 6 | -------------------------------------------------------------------------------- /test/unit/src/net/dfranek/typoscript/parser/test.ts: -------------------------------------------------------------------------------- 1 | seite = PAGE 2 | seite.headerData.10.value = test 3 | seite { 4 | config.test = 129 5 | test2 = [10.w] + 16,19 6 | test3 { 7 | test = 4 8 | } 9 | test4 = 3 10 | test8 < seite.config.test 11 | test5 ( 12 | asdasdasdasdasdsa 13 | ) 14 | } -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/TSExample.ts: -------------------------------------------------------------------------------- 1 | # Comment 2 | 3 | /* 4 | * Line Comment 5 | */ 6 | page = PAGE 7 | page.config.SUBTEMPLATE = {$SUBTEMPLATE} 8 | 9 | headerimg.file { 10 | XY = [10.w]+2,20 11 | } 12 | 13 | [globalVar=TSFE:type = 0] 14 | page.typeNum = 0 15 | [global] 16 | 17 | page.10.value ( 18 | Multi 19 | Line 20 | Value 21 | ) 22 | 23 | plugin.tx_something_pi1.10 > -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/Bundle.properties: -------------------------------------------------------------------------------- 1 | LBL_TSEditorTab=&Source 2 | Templates/TypoScript/TSTemplate.ts=Empty TS file 3 | Templates/TypoScript/TSTemplateComments.ts=Empty TS file with coding sections 4 | Templates/TypoScript/TSTemplateHTML5Advanced.ts=Advanced HTML5 TS file 5 | Templates/TypoScript/TSTemplateHTML5Multilingual.ts=Advanced HTML5 TS 6 | Templates/TypoScript/TSTemplateRTE.ts=TS file for RTE configuration 7 | 8 | text/x-typoscript=TypoScript -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This Project aims to provide support for the TypoScript Language used by TYPO3. 2 | 3 | The currently implemented features are: 4 | - Syntax highlighting (based on the file tokenizetyposcript.js from the TYPO3 extension t3editor). 5 | - a navigator for all properties declared in a file 6 | - a check for syntax errors (thanks to familie-redlich) 7 | - Code folding 8 | - a parser, responsible for syntax errors, navigator and other things 9 | - Code completion 10 | -------------------------------------------------------------------------------- /nbproject/project.properties: -------------------------------------------------------------------------------- 1 | auxiliary.org-netbeans-spi-editor-hints-projects.perProjectHintSettingsFile=nbproject/cfg_hints.xml 2 | javac.source=1.7 3 | javac.compilerargs=-Xlint -Xlint:-serial 4 | javadoc.arch=${basedir}/arch.xml 5 | license.file=gpl.txt 6 | nbm.homepage=https://github.com/dfranek/Netbeans-TypoScript 7 | nbm.module.author=Daniel Franek 8 | 9 | nbm.needs.restart=true 10 | spec.version.base=1.9 11 | 12 | keystore=nbproject/private/keystore 13 | nbm_alias=dfranek 14 | -------------------------------------------------------------------------------- /nbproject/genfiles.properties: -------------------------------------------------------------------------------- 1 | build.xml.data.CRC32=07aabe4a 2 | build.xml.script.CRC32=4a07b388 3 | build.xml.stylesheet.CRC32=a56c6a5b@2.70.1 4 | # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. 5 | # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. 6 | nbproject/build-impl.xml.data.CRC32=07aabe4a 7 | nbproject/build-impl.xml.script.CRC32=a99342a4 8 | nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.70.1 9 | -------------------------------------------------------------------------------- /nbproject/platform.properties: -------------------------------------------------------------------------------- 1 | cluster.path=\ 2 | ${nbplatform.active.dir}/apisupport:\ 3 | ${nbplatform.active.dir}/cnd:\ 4 | ${nbplatform.active.dir}/dlight:\ 5 | ${nbplatform.active.dir}/enterprise:\ 6 | ${nbplatform.active.dir}/ergonomics:\ 7 | ${nbplatform.active.dir}/groovy:\ 8 | ${nbplatform.active.dir}/harness:\ 9 | ${nbplatform.active.dir}/ide:\ 10 | ${nbplatform.active.dir}/java:\ 11 | ${nbplatform.active.dir}/javacard:\ 12 | ${nbplatform.active.dir}/mobility:\ 13 | ${nbplatform.active.dir}/nb:\ 14 | ${nbplatform.active.dir}/php:\ 15 | ${nbplatform.active.dir}/platform:\ 16 | ${nbplatform.active.dir}/profiler:\ 17 | ${nbplatform.active.dir}/websvccommon 18 | nbjdk.active=default 19 | nbplatform.active=default 20 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/Bundle.properties: -------------------------------------------------------------------------------- 1 | OpenIDE-Module-Name=TypoScript 2 | OpenIDE-Module-Display-Category=Web 3 | OpenIDE-Module-Long-Description=\ 4 | TypoScript Support for NetBeans IDE 5 | OpenIDE-Module-Short-Description=TypoScript Support for NetBeans IDE 6 | 7 | Services/MIMEResolver/TSResolver.xml=TS Files 8 | 9 | 10 | text/x-typoscript=TypoScript 11 | 12 | operator=Operator 13 | brace=Braces 14 | comment=Comments 15 | value=Values 16 | condition=Conditions 17 | ts=TypoScript 18 | keyword=Keywords 19 | reserved=Reserved Words 20 | whitespace=Whitespace 21 | error=Errors 22 | constant=Constants 23 | extension=Extensions 24 | 25 | net_dfranek_typoscript_update_center=http://netbeans.dfranek.net/updates.xml.php 26 | Services/AutoupdateType/net_dfranek_typoscript_update_center.instance=TypoScript Update Center 27 | 28 | LBL_TS_loader_name=TS Files 29 | LBL_TSEditorTab=&Source -------------------------------------------------------------------------------- /helper/json.php: -------------------------------------------------------------------------------- 1 | type as $type) { 8 | $typeId = (string)$type['id']; 9 | if($typeId == 'GB_TEXT') { 10 | $typeId = 'GIFBUILDER_TEXT'; 11 | } 12 | if($typeId == 'GB_IMAGE') { 13 | $typeId = 'GIFBUILDER_IMAGE'; 14 | } 15 | 16 | $types[$typeId]['extendsType'] = (string)$type['extends']; 17 | foreach ($type->property as $property) { 18 | $types[$typeId]['properties'][(string)$property['name']] = array( 19 | 'type' => (string)$property['type'], 20 | 'defaultValue' => (string)$property->default, 21 | 'description' => nl2br((string)$property->description), 22 | ); 23 | } 24 | } 25 | echo "
";
26 | print_r($types);
27 | echo "
"; 28 | file_put_contents('tsref.json', json_encode($types)); 29 | 30 | ?> -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/FontAndColors.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/templates/TSTemplateComments.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Project: ${project.displayName} - ${project.name} 3 | * Version: 1.0.0 4 | * Date: ${date} ${time} 5 | * Author: ${user} 6 | * 7 | * Coded with Netbeans! 8 | */ 9 | 10 | #| --- Plugin ----------------------------------------------------------------------------------------- |# 11 | 12 | 13 | #| --- Libs ------------------------------------------------------------------------------------------- |# 14 | 15 | 16 | #| --- tt_content ------------------------------------------------------------------------------------- |# 17 | 18 | 19 | #| --- Code Cleanup ----------------------------------------------------------------------------------- |# 20 | lib.parseFunc_RTE.nonTypoTagStdWrap.encapsLines.addAttributes.P.class = 21 | 22 | 23 | #| --- Page Config ------------------------------------------------------------------------------------ |# 24 | 25 | 26 | #| --- Header & Body ---------------------------------------------------------------------------------- |# 27 | 28 | 29 | #| --- Template --------------------------------------------------------------------------------------- |# 30 | 31 | 32 | #| --- Markers & Subparts ----------------------------------------------------------------------------- |# 33 | 34 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/parser/TSParserResult.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | package net.dfranek.typoscript.parser; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import net.dfranek.typoscript.lexer.TSTokenId; 10 | import net.dfranek.typoscript.parser.ast.TSASTNode; 11 | import org.netbeans.api.lexer.TokenSequence; 12 | import org.netbeans.modules.csl.api.Error; 13 | import org.netbeans.modules.csl.api.OffsetRange; 14 | import org.netbeans.modules.csl.spi.ParserResult; 15 | import org.netbeans.modules.parsing.api.Snapshot; 16 | 17 | /** 18 | * 19 | * @author Eric Waldburger 20 | */ 21 | public class TSParserResult extends ParserResult { 22 | 23 | private final List errors; 24 | private boolean valid = true; 25 | private TSASTNode tree; 26 | private TokenSequence sequence; 27 | private List codeblocks; 28 | 29 | public TSParserResult(Snapshot snapshot) { 30 | super(snapshot); 31 | this.errors = new ArrayList<>(); 32 | this.codeblocks = new ArrayList<>(); 33 | } 34 | 35 | private TSParserResult(Snapshot snapshot, TokenSequence source) { 36 | super(snapshot); 37 | this.errors = new ArrayList<>(); 38 | } 39 | 40 | @Override 41 | public List getDiagnostics() { 42 | return errors; 43 | } 44 | 45 | public void addError(Error e) { 46 | errors.add(e); 47 | } 48 | 49 | public void addCodeBlock(OffsetRange r) { 50 | codeblocks.add(r); 51 | } 52 | 53 | @Override 54 | protected void invalidate() { 55 | valid = false; 56 | } 57 | 58 | public TSASTNode getTree() { 59 | return tree; 60 | } 61 | 62 | public void setTree(TSASTNode tree) { 63 | this.tree = tree; 64 | } 65 | 66 | public void setSequence(TokenSequence sequence) { 67 | this.sequence = sequence; 68 | } 69 | 70 | public TokenSequence getSequence() { 71 | return this.sequence; 72 | } 73 | 74 | public List getCodeBlocks() { 75 | return codeblocks; 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/layer.xml: -------------------------------------------------------------------------------- 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 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /nbproject/build-impl.xml: -------------------------------------------------------------------------------- 1 | 2 | 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 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | 1.2.9: 2 | - added highlighting for constants 3 | - added highlighting for extensions 4 | - changed highlighting for copied values, e.g. plugin.schluessel.config.value < tmp.schluessel.config.default 5 | - changed default style for conditions 6 | - fixed bug with code completion 7 | 1.2.10 8 | - fixed a severe bug in the lexer 9 | 1.3.0 10 | - Source/History now works 11 | - errors for non closed bracket are now added in the parser 12 | - fixed bug with code completion 13 | 1.3.1 14 | - fixed bug in lexer with opening curly brace 15 | 1.3.2 16 | - fixed Issue 12 (Matching constants fails when they contain a dot ) 17 | - more keywords were added to xml 18 | 1.3.3 19 | - fixed bug with constants and xml 20 | 1.3.8 21 | - added more filetypes to resolver: 22 | setup.txt 23 | constants.txt 24 | ext_conf_template.txt 25 | ext_typoscript_setup.txt 26 | ext_typoscript_constants.txt 27 | 1.4.0 28 | - removed the internal class for keywords, moved all keywords to external xml file 29 | - parser now builds a tree 30 | - the navigator now shows a tree with all the properties 31 | 1.4.1 32 | - a bug in the lexer was fixed (issue #16) 33 | 1.4.2 34 | - fixed an error in the lexer (issue #17) 35 | - fixed an error in the parser 36 | 1.4.3 37 | - fixed slow loading of editor (issue #18) 38 | 1.5.0 39 | - improved code completion with parse result 40 | - parsing now sets correct types for stdWrap and config 41 | - help is now shown for some types in code completion 42 | 1.5.1 43 | - fixed bug with documentation 44 | - further improved documentation, inherited properties are now shown 45 | - improved parsing, now sets correct type for IMAGE and TEXT inside GIFBUILDER, as well as for NO, RO etc. 46 | 1.5.2 47 | - added more and better icons (thanks to familie redlich) 48 | 1.5.3 49 | - added more icons 50 | - conditions are now an own tree in the parser 51 | 1.5.4 52 | - fixed small bugs in code completion 53 | 1.6.0. 54 | - added "Go to Declaration" for copied properties 55 | 1.7.0 56 | - added auto complete for square brackets and curly braces 57 | 1.7.1 58 | - fixed bug with inserting of end parantheses in multiline values 59 | 1.7.2 60 | - some cleanup, reduced layer.xml, more annotations 61 | 1.8.0 62 | - Release for NetBeans 8.1 63 | - HTML/CSS Embedded Markup -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/templates/TSTemplate.html: -------------------------------------------------------------------------------- 1 | 36 | 37 | 38 | 39 | 40 | 41 | Creates empty TypoScript file. You can edit the file in the IDE's Source Editor. 42 | To change this template, choose Tools | Template Manager 43 | and open the template in the editor. 44 | 45 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/templates/TSTemplateHTML5Advanced.html: -------------------------------------------------------------------------------- 1 | 36 | 37 | 38 | 39 | 40 | 41 | Creates empty TypoScript file for HTML5. You can edit the file in the IDE's Source Editor. 42 | To change this template, choose Tools | Template Manager 43 | and open the template in the editor. 44 | 45 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/templates/TSTemplateRTE.html: -------------------------------------------------------------------------------- 1 | 36 | 37 | 38 | 39 | 40 | 41 | Creates empty TSConfig file for a RTE Configuaration. You can edit the file in the IDE's Source Editor. 42 | To change this template, choose Tools | Template Manager 43 | and open the template in the editor. 44 | 45 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/templates/TSTemplateComments.html: -------------------------------------------------------------------------------- 1 | 36 | 37 | 38 | 39 | 40 | 41 | Creates empty TypoScript file divided into Sections. You can edit the file in the IDE's Source Editor. 42 | To change this template, choose Tools | Template Manager 43 | and open the template in the editor. 44 | 45 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/templates/TSTemplateHTML5Multilingual.html: -------------------------------------------------------------------------------- 1 | 36 | 37 | 38 | 39 | 40 | 41 | Creates empty TypoScript file with multi language support. You can edit the file in the IDE's Source Editor. 42 | To change this template, choose Tools | Template Manager 43 | and open the template in the editor. 44 | 45 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/lexer/TSLexerState.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.lexer; 40 | 41 | /** 42 | * Enum with the possible states for TypoScript scanner. 43 | * 44 | * @author Daniel Franek 45 | */ 46 | public enum TSLexerState { 47 | IN_VALUE, 48 | IN_COMMENT, 49 | IN_PARANTHESE, 50 | IN_REGEXP, 51 | DEFAULT 52 | } -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/TSResolver.xml: -------------------------------------------------------------------------------- 1 | 2 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/indent/TSBracesMatcherFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.indent; 40 | 41 | import org.netbeans.spi.editor.bracesmatching.BracesMatcher; 42 | import org.netbeans.spi.editor.bracesmatching.BracesMatcherFactory; 43 | import org.netbeans.spi.editor.bracesmatching.MatcherContext; 44 | 45 | /** 46 | * 47 | * @author Daniel Franek 48 | */ 49 | public class TSBracesMatcherFactory implements BracesMatcherFactory{ 50 | 51 | @Override 52 | public BracesMatcher createMatcher(MatcherContext mc) { 53 | return new TSBracesMatcher(mc); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/completion/tsref/TSRefProperty.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.completion.tsref; 40 | 41 | /** 42 | * 43 | * @author Daniel Franek 44 | */ 45 | public class TSRefProperty { 46 | private String defaultValue; 47 | private String description; 48 | private String type; 49 | 50 | /** 51 | * @return the defaultValue 52 | */ 53 | public String getDefaultValue() { 54 | return defaultValue; 55 | } 56 | 57 | /** 58 | * @return the description 59 | */ 60 | public String getDescription() { 61 | return description; 62 | } 63 | 64 | /** 65 | * @return the type 66 | */ 67 | public String getType() { 68 | return type; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/templates/TSTemplateHTML5Advanced.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Project: ${project.displayName} - ${project.name} 3 | * Version: 1.0.0 4 | * Date: ${date} ${time} 5 | * Author: ${user} 6 | * 7 | * Coded with Netbeans! 8 | */ 9 | 10 | #| --- Plugin ----------------------------------------------------------------------------------------- |# 11 | 12 | 13 | #| --- Libs ------------------------------------------------------------------------------------------- |# 14 | 15 | 16 | #| --- tt_content ------------------------------------------------------------------------------------- |# 17 | 18 | 19 | #| --- Code Cleanup ----------------------------------------------------------------------------------- |# 20 | lib.parseFunc_RTE.nonTypoTagStdWrap.encapsLines.addAttributes.P.class = 21 | 22 | 23 | #| --- System & Page Config --------------------------------------------------------------------------- |# 24 | config { 25 | uniqueLinkVars = 1 26 | sys_language_uid = 0 27 | language = de 28 | locale_all = de_DE 29 | meaningfulTempFilePrefix = 64 30 | } 31 | 32 | page = PAGE 33 | page { 34 | config { 35 | doctype = html5 36 | disableImgBorderAttr = 1 37 | disablePrefixComment = 1 38 | htmlTag_langKey = de-DE 39 | meta.language = de 40 | spamProtectEmailAddresses = 2 41 | spamProtectEmailAddresses_atSubst = (at) 42 | spamProtectEmailAddresses_lastDotSubst = (dot) 43 | pageTitleFirst = 1 44 | removeDefaultJS = 1 45 | inlineStyle2TempFile = 1 46 | } 47 | 48 | 49 | #| --- Header & Body ---------------------------------------------------------------------------------- |# 50 | meta { 51 | keywords.field = keywords 52 | keywords.ifEmpty ( 53 | // Enter default keywords of the website here 54 | ) 55 | description.field = description 56 | description.ifEmpty ( 57 | // Enter default description of the website here 58 | ) 59 | FLAGS.DC = 0 60 | robots = 61 | author = 62 | revisited-after = 14 63 | audience = 64 | page-topic = 65 | MSSmartTagsPreventParsing = true 66 | imagetoolbar = false 67 | } 68 | includeCSS { 69 | screen = fileadmin/ 70 | mobil = fileadmin/ 71 | print = fileadmin/ 72 | print.media = print 73 | } 74 | includeJS { 75 | jQuery = fileadmin/ 76 | } 77 | includeJSFooter { 78 | tracking = fileadmin/ 79 | } 80 | } 81 | 82 | 83 | #| --- Template --------------------------------------------------------------------------------------- |# 84 | page.10 = TEMPLATE 85 | page.10 { 86 | template = FILE 87 | workOnSubpart = DOC 88 | template.file = fileadmin/templates/standard.html 89 | } 90 | 91 | 92 | #| --- Markers & Subparts ----------------------------------------------------------------------------- |# 93 | 94 | -------------------------------------------------------------------------------- /test/unit/src/net/dfranek/typoscript/parser/TSParserTestUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.parser; 40 | 41 | import junit.framework.TestCase; 42 | import net.dfranek.typoscript.parser.ast.TSASTNode; 43 | import net.dfranek.typoscript.parser.ast.TSASTNodeType; 44 | 45 | /** 46 | * 47 | * @author Daniel Franek 48 | */ 49 | public class TSParserTestUtils extends TestCase { 50 | 51 | public static void assertNodeEquals(TSASTNode node, String nodeName, TSASTNodeType type, String value, int size) { 52 | assertEquals(node.getName(), nodeName); 53 | assertEquals(node.getType(), type); 54 | assertEquals(node.getValue(), value); 55 | assertTrue(node.getChildren().size() == size); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/completion/tsref/TSRefType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.completion.tsref; 40 | 41 | import java.util.HashMap; 42 | import java.util.Map; 43 | 44 | /** 45 | * 46 | * @author Daniel Franek 47 | */ 48 | public class TSRefType { 49 | private final HashMap properties = new HashMap<>(); 50 | private String extendsType; 51 | 52 | /** 53 | * @return the properties 54 | */ 55 | public TSRefProperty getProperty(String name) { 56 | return getProperties().get(name); 57 | } 58 | 59 | /** 60 | * @return the extendsType 61 | */ 62 | public String getExtends() { 63 | return extendsType; 64 | } 65 | 66 | public void setExtends(String extendsStr) { 67 | this.extendsType = extendsStr; 68 | } 69 | 70 | /** 71 | * @return the properties 72 | */ 73 | public HashMap getProperties() { 74 | return properties; 75 | } 76 | 77 | public void addProperties(HashMap properties) { 78 | for (Map.Entry entry : properties.entrySet()) { 79 | String name = entry.getKey(); 80 | TSRefProperty tSRefProperty = entry.getValue(); 81 | this.properties.put(name, tSRefProperty); 82 | } 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/templates/TSTemplateHTML5Multilingual.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Project: ${project.displayName} - ${project.name} 3 | * Version: 1.0.0 4 | * Date: ${date} ${time} 5 | * Author: ${user} 6 | * 7 | * Coded with Netbeans! 8 | */ 9 | 10 | #| --- Plugin ----------------------------------------------------------------------------------------- |# 11 | 12 | 13 | #| --- Libs ------------------------------------------------------------------------------------------- |# 14 | 15 | 16 | #| --- tt_content ------------------------------------------------------------------------------------- |# 17 | 18 | 19 | #| --- Code Cleanup ----------------------------------------------------------------------------------- |# 20 | lib.parseFunc_RTE.nonTypoTagStdWrap.encapsLines.addAttributes.P.class = 21 | 22 | 23 | #| --- System & Page Config --------------------------------------------------------------------------- |# 24 | config { 25 | linkVars = L(0-3) 26 | uniqueLinkVars = 1 27 | language = de 28 | locale_all = de_DE 29 | sys_language_uid = 0 30 | sys_language_mode = content_fallback 31 | meaningfulTempFilePrefix = 64 32 | } 33 | [globalVar = GP:L = 1] 34 | config { 35 | sys_language_uid = 1 36 | language = en 37 | locale_all = en_EN 38 | } 39 | [global] 40 | [globalVar = GP:L = 2] 41 | config { 42 | sys_language_uid = 2 43 | language = es 44 | locale_all = es_ES 45 | } 46 | [global] 47 | [globalVar = GP:L = 3] 48 | config { 49 | sys_language_uid = 3 50 | language = fr 51 | locale_all = fr_FR 52 | } 53 | [global] 54 | 55 | page = PAGE 56 | page { 57 | config { 58 | doctype = html5 59 | disableImgBorderAttr = 1 60 | disablePrefixComment = 1 61 | htmlTag_langKey = de-DE 62 | meta.language = de 63 | spamProtectEmailAddresses = 2 64 | spamProtectEmailAddresses_atSubst = (at) 65 | spamProtectEmailAddresses_lastDotSubst = (dot) 66 | pageTitleFirst = 1 67 | removeDefaultJS = 1 68 | inlineStyle2TempFile = 1 69 | } 70 | 71 | 72 | #| --- Header & Body ---------------------------------------------------------------------------------- |# 73 | meta { 74 | keywords.field = keywords 75 | keywords.ifEmpty ( 76 | // Enter default keywords of the website here 77 | ) 78 | description.field = description 79 | description.ifEmpty ( 80 | // Enter default description of the website here 81 | ) 82 | FLAGS.DC = 0 83 | robots = 84 | author = 85 | revisited-after = 14 86 | audience = 87 | page-topic = 88 | MSSmartTagsPreventParsing = true 89 | imagetoolbar = false 90 | } 91 | includeCSS { 92 | screen = fileadmin/ 93 | mobil = fileadmin/ 94 | print = fileadmin/ 95 | print.media = print 96 | } 97 | includeJS { 98 | jQuery = fileadmin/ 99 | } 100 | includeJSFooter { 101 | tracking = fileadmin/ 102 | } 103 | } 104 | 105 | 106 | #| --- Template --------------------------------------------------------------------------------------- |# 107 | page.10 = TEMPLATE 108 | page.10 { 109 | template = FILE 110 | workOnSubpart = DOC 111 | template.file = fileadmin/templates/standard.html 112 | } 113 | 114 | 115 | #| --- Markers & Subparts ----------------------------------------------------------------------------- |# 116 | 117 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/completion/tsref/TSRef.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.completion.tsref; 40 | 41 | import com.google.gson.Gson; 42 | import com.google.gson.reflect.TypeToken; 43 | import java.io.InputStreamReader; 44 | import java.lang.reflect.Type; 45 | import java.util.HashMap; 46 | import net.dfranek.typoscript.lexer.TSLexerUtils; 47 | 48 | /** 49 | * 50 | * @author Daniel Franek 51 | */ 52 | public class TSRef { 53 | 54 | protected static HashMap tsref; 55 | 56 | public static void initTSRef() { 57 | Gson gson = new Gson(); 58 | Type tsrefType = new TypeToken>(){}.getType(); 59 | tsref = gson.fromJson(new InputStreamReader(TSLexerUtils.class.getResourceAsStream("/net/dfranek/typoscript/resources/tsref.json")), tsrefType); 60 | } 61 | 62 | public static TSRefType getHelpForType(String type) { 63 | TSRefType t = null; 64 | if (tsref.containsKey(type)) { 65 | t = tsref.get(type); 66 | t = addBaseType(t); 67 | } 68 | 69 | return t; 70 | } 71 | 72 | private static TSRefType addBaseType(TSRefType t) { 73 | if (!t.getExtends().isEmpty()) { 74 | TSRefType baseType = tsref.get(t.getExtends()); 75 | t.addProperties(baseType.getProperties()); 76 | t.setExtends(baseType.getExtends()); 77 | t = addBaseType(t); 78 | } 79 | return t; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/embedding/HtmlEmbeddingProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | 40 | package net.dfranek.typoscript.embedding; 41 | 42 | import java.util.ArrayList; 43 | import java.util.List; 44 | import net.dfranek.typoscript.lexer.TSTokenId; 45 | import org.netbeans.api.lexer.Token; 46 | import org.netbeans.api.lexer.TokenSequence; 47 | import org.netbeans.modules.parsing.api.Embedding; 48 | import org.netbeans.modules.parsing.api.Snapshot; 49 | import org.netbeans.modules.parsing.spi.EmbeddingProvider; 50 | 51 | /** 52 | * 53 | * @author Daniel Franek 54 | */ 55 | @EmbeddingProvider.Registration( 56 | mimeType="text/x-typoscript", 57 | targetMimeType="text/html" 58 | ) 59 | public class HtmlEmbeddingProvider extends EmbeddingProvider { 60 | 61 | private final String HTML_MIME_TYPE = "text/html"; 62 | 63 | @Override 64 | public List getEmbeddings(Snapshot snapshot) { 65 | final List embeddings = new ArrayList<>(); 66 | final TokenSequence ts = snapshot.getTokenHierarchy().tokenSequence(TSTokenId.language()); 67 | 68 | while (ts.moveNext()) { 69 | Token token = ts.token(); 70 | if(token.id() == TSTokenId.TS_MULTILINE_VALUE) { 71 | embeddings.add(snapshot.create(ts.offset(), token.length(), HTML_MIME_TYPE)); 72 | } 73 | } 74 | 75 | return embeddings; 76 | } 77 | 78 | @Override 79 | public int getPriority() { 80 | return 50; 81 | } 82 | 83 | @Override 84 | public void cancel() { 85 | // do nothing 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/completion/TSCompletionResult.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.completion; 40 | 41 | import java.util.ArrayList; 42 | import java.util.Collection; 43 | import java.util.logging.Logger; 44 | import javax.swing.text.BadLocationException; 45 | import javax.swing.text.Document; 46 | import org.netbeans.modules.csl.api.CodeCompletionContext; 47 | import org.netbeans.modules.csl.api.CompletionProposal; 48 | import org.netbeans.modules.csl.spi.DefaultCompletionResult; 49 | import org.openide.util.Exceptions; 50 | /** 51 | * 52 | * @author daniel 53 | */ 54 | class TSCompletionResult extends DefaultCompletionResult { 55 | 56 | private final CodeCompletionContext context; 57 | 58 | public TSCompletionResult(CodeCompletionContext completionContext) { 59 | super(new ArrayList(), false); 60 | context = completionContext; 61 | } 62 | 63 | public void addAll(final Collection proposals) { 64 | list.addAll(proposals); 65 | } 66 | 67 | public void add(CompletionProposal proposal) { 68 | list.add(proposal); 69 | } 70 | 71 | @Override 72 | public void afterInsert(CompletionProposal cp) { 73 | Document doc = context.getParserResult().getSnapshot().getSource().getDocument(true); 74 | try { 75 | // Remove typed characters 76 | Logger.getLogger(TSCompletionResult.class.getName()).finest(doc.getText(cp.getAnchorOffset()-context.getPrefix().length(), context.getPrefix().length())); 77 | doc.remove(cp.getAnchorOffset()-context.getPrefix().length(), context.getPrefix().length()); 78 | } catch (BadLocationException ex) { 79 | Exceptions.printStackTrace(ex); 80 | } 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/parser/TSBracketNode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.parser; 40 | 41 | /** 42 | * 43 | * @author Eric Waldburger 44 | */ 45 | public class TSBracketNode { 46 | 47 | private TSBracketNode next; 48 | private TSBracketNode prev; 49 | private String value; 50 | private int offset; 51 | 52 | public TSBracketNode() { 53 | this.next = null; 54 | this.prev = null; 55 | this.value = ""; 56 | } 57 | 58 | public TSBracketNode(String inVal, TSBracketNode inPrev) { 59 | this.next = null; 60 | this.prev = inPrev; 61 | this.value = inVal; 62 | this.offset = 0; 63 | } 64 | 65 | public TSBracketNode(String inVal, TSBracketNode inPrev, int offset) { 66 | this.next = null; 67 | this.prev = inPrev; 68 | this.value = inVal; 69 | this.offset = offset; 70 | } 71 | 72 | public TSBracketNode(String inVal, TSBracketNode inNext, TSBracketNode inPrev) { 73 | this.next = inNext; 74 | this.prev = inPrev; 75 | this.value = inVal; 76 | this.offset = 0; 77 | } 78 | 79 | public TSBracketNode(String inVal, TSBracketNode inNext, TSBracketNode inPrev, int offset) { 80 | this.next = inNext; 81 | this.prev = inPrev; 82 | this.value = inVal; 83 | this.offset = offset; 84 | } 85 | 86 | public TSBracketNode getNext() { 87 | return next; 88 | } 89 | 90 | public TSBracketNode getPrev() { 91 | return prev; 92 | } 93 | 94 | public void setPrev(TSBracketNode prev) { 95 | this.prev = prev; 96 | } 97 | 98 | public void setNext(TSBracketNode next) { 99 | this.next = next; 100 | } 101 | 102 | public String getValue() { 103 | return value; 104 | } 105 | 106 | public void setValue(String value) { 107 | this.value = value; 108 | } 109 | 110 | /** 111 | * @return the offset 112 | */ 113 | public int getOffset() { 114 | return offset; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/parser/TSError.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.parser; 40 | 41 | import org.netbeans.modules.csl.api.Severity; 42 | import org.openide.filesystems.FileObject; 43 | 44 | /** 45 | * 46 | * @author Daniel Franek 47 | */ 48 | public class TSError implements org.netbeans.modules.csl.api.Error{ 49 | 50 | private final String displayName; 51 | 52 | private final FileObject file; 53 | private final int startPosition; 54 | private final int endPosition; 55 | private final Severity severity; 56 | private final Object[] parameters; 57 | 58 | public TSError(String name, FileObject file, int start, int end, Severity severity, Object[] params) { 59 | displayName = name; 60 | this.file = file; 61 | startPosition = start; 62 | endPosition = end; 63 | this.severity = severity; 64 | this.parameters = params; 65 | } 66 | 67 | @Override 68 | public String getDisplayName() { 69 | return displayName; 70 | } 71 | 72 | @Override 73 | public String getDescription() { 74 | return null; 75 | } 76 | 77 | @Override 78 | public String getKey() { 79 | return "[" + startPosition + "," + endPosition + "]-" + displayName ; 80 | } 81 | 82 | @Override 83 | public FileObject getFile() { 84 | return this.file; 85 | } 86 | 87 | @Override 88 | public int getStartPosition() { 89 | return startPosition; 90 | } 91 | 92 | @Override 93 | public int getEndPosition() { 94 | return endPosition; 95 | } 96 | 97 | @Override 98 | public boolean isLineError() { 99 | return true; 100 | } 101 | 102 | @Override 103 | public Severity getSeverity() { 104 | return severity; 105 | } 106 | 107 | @Override 108 | public Object[] getParameters() { 109 | return parameters; 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/completion/TSElement.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.completion; 40 | 41 | import java.util.Collections; 42 | import java.util.Set; 43 | import net.dfranek.typoscript.TSLanguage; 44 | import org.netbeans.modules.csl.api.ElementHandle; 45 | import org.netbeans.modules.csl.api.ElementKind; 46 | import org.netbeans.modules.csl.api.Modifier; 47 | import org.netbeans.modules.csl.api.OffsetRange; 48 | import org.netbeans.modules.csl.spi.ParserResult; 49 | import org.openide.filesystems.FileObject; 50 | 51 | /** 52 | * 53 | * @author Daniel Franek 54 | */ 55 | public class TSElement implements ElementHandle { 56 | 57 | private final CharSequence name; 58 | private final String doc; 59 | 60 | public TSElement(CharSequence name) { 61 | this.name = name; 62 | this.doc = null; 63 | } 64 | 65 | public TSElement(CharSequence name, String doc) { 66 | this.name = name; 67 | this.doc = doc; 68 | } 69 | 70 | @Override 71 | public FileObject getFileObject() { 72 | return null; 73 | } 74 | 75 | @Override 76 | public String getMimeType() { 77 | return TSLanguage.TS_MIME_TYPE; 78 | } 79 | 80 | @Override 81 | public String getName() { 82 | return name.toString(); 83 | } 84 | 85 | @Override 86 | public String getIn() { 87 | return null; 88 | } 89 | 90 | @Override 91 | public ElementKind getKind() { 92 | return ElementKind.VARIABLE; 93 | } 94 | 95 | @Override 96 | public Set getModifiers() { 97 | return Collections.emptySet(); 98 | } 99 | 100 | @Override 101 | public boolean signatureEquals(ElementHandle eh) { 102 | return false; 103 | } 104 | 105 | @Override 106 | public OffsetRange getOffsetRange(ParserResult pr) { 107 | return null; 108 | } 109 | 110 | public String getDocumentation() { 111 | return doc; 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/parser/TSParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.parser; 40 | 41 | import java.util.logging.Level; 42 | import java.util.logging.Logger; 43 | import javax.swing.event.ChangeListener; 44 | import net.dfranek.typoscript.lexer.TSTokenId; 45 | import org.netbeans.api.lexer.TokenSequence; 46 | import org.netbeans.modules.csl.spi.ParserResult; 47 | import org.netbeans.modules.parsing.api.Snapshot; 48 | import org.netbeans.modules.parsing.api.Task; 49 | import org.netbeans.modules.parsing.spi.ParseException; 50 | import org.netbeans.modules.parsing.spi.Parser; 51 | import org.netbeans.modules.parsing.spi.SourceModificationEvent; 52 | 53 | /** 54 | * 55 | * @author Daniel Franek 56 | */ 57 | public class TSParser extends Parser { 58 | 59 | private Snapshot snapshot; 60 | private ParserResult result = null; 61 | private static final Logger LOGGER = Logger.getLogger(TSParser.class.getName()); 62 | 63 | @Override 64 | public void parse(Snapshot snapshot, Task task, SourceModificationEvent sme) throws ParseException { 65 | this.snapshot = snapshot; 66 | //File split into tokens 67 | TokenSequence sequence = snapshot.getTokenHierarchy().tokenSequence(TSTokenId.getLanguage()); 68 | try { 69 | result = parseSource(sequence); 70 | } catch (Exception e) { 71 | LOGGER.log(Level.FINE, "Exception during parsing: {0}", e); 72 | result = new TSParserResult(snapshot); 73 | } 74 | } 75 | 76 | @Override 77 | public Result getResult(Task task) throws ParseException { 78 | return result; 79 | } 80 | 81 | @Override 82 | public void addChangeListener(ChangeListener cl) { 83 | } 84 | 85 | @Override 86 | public void removeChangeListener(ChangeListener cl) { 87 | } 88 | 89 | private ParserResult parseSource(TokenSequence source) { 90 | ParserResult pResult; 91 | TSTokenParser p = new TSTokenParser(source, snapshot); 92 | pResult = p.analyze(); 93 | 94 | return pResult; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/lexer/TSLanguageHierarchy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.lexer; 40 | import java.util.*; 41 | import net.dfranek.typoscript.TSLanguage; 42 | import org.netbeans.api.lexer.InputAttributes; 43 | import org.netbeans.api.lexer.Language; 44 | import org.netbeans.api.lexer.LanguagePath; 45 | import org.netbeans.api.lexer.Token; 46 | import org.netbeans.spi.lexer.*; 47 | 48 | /** 49 | * 50 | * @author Daniel Franek 51 | */ 52 | public class TSLanguageHierarchy extends LanguageHierarchy { 53 | 54 | private static EnumSet tokens; 55 | private static Map idToToken; 56 | 57 | private static void init () { 58 | tokens = EnumSet.allOf(TSTokenId.class); 59 | idToToken = new HashMap<> (); 60 | for (TSTokenId token : tokens) 61 | idToToken.put (token.ordinal (), token); 62 | } 63 | 64 | static synchronized TSTokenId getToken (int id) { 65 | if (idToToken == null) 66 | init (); 67 | return idToToken.get (id); 68 | } 69 | 70 | @Override 71 | protected synchronized Collection createTokenIds() { 72 | if (tokens == null) 73 | init (); 74 | return tokens; 75 | } 76 | 77 | @Override 78 | protected synchronized Lexer createLexer(LexerRestartInfo lri) { 79 | return new TSLexer (lri); 80 | } 81 | 82 | @Override 83 | protected String mimeType() { 84 | return TSLanguage.TS_MIME_TYPE; 85 | } 86 | 87 | @Override 88 | protected LanguageEmbedding embedding(Token token, LanguagePath languagePath, InputAttributes inputAttributes) { 89 | if(token.id() == TSTokenId.TS_MULTILINE_VALUE) { 90 | Language language = Language.find("text/html"); 91 | if(language != null) { 92 | return LanguageEmbedding.create(language, 0, 0); 93 | } 94 | } 95 | return null; 96 | } 97 | 98 | 99 | } 100 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/lexer/TSLexer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.lexer; 40 | 41 | import java.io.IOException; 42 | import java.util.logging.Level; 43 | import java.util.logging.Logger; 44 | import org.netbeans.api.lexer.Token; 45 | import org.netbeans.spi.lexer.Lexer; 46 | import org.netbeans.spi.lexer.LexerRestartInfo; 47 | import org.netbeans.spi.lexer.TokenFactory; 48 | 49 | /** 50 | * 51 | * @author Daniel Franek 52 | */ 53 | public class TSLexer implements Lexer { 54 | 55 | private final LexerRestartInfo info; 56 | private final TokenFactory tokenFactory; 57 | private final TSScanner scanner; 58 | 59 | TSLexer(LexerRestartInfo info) { 60 | this.info = info; 61 | scanner = new TSScanner(info); 62 | tokenFactory = info.tokenFactory(); 63 | TSLexerUtils.initKeywords(); 64 | } 65 | 66 | /** 67 | * Returns the next Token. Calls TSScanner.nextToken to determine type of the token. 68 | * 69 | * @return the next token 70 | */ 71 | @Override 72 | public Token nextToken() { 73 | 74 | try { 75 | TSTokenId tokenId = scanner.nextToken(); 76 | int readLen = scanner.getReadLength(); 77 | Token token = null; 78 | if (readLen < 1) return null; 79 | 80 | if (tokenId != null) { 81 | token = tokenFactory.createToken(tokenId); 82 | } 83 | return token; 84 | } catch (IOException ex) { 85 | Logger.getLogger(TSLexer.class.getName()).log(Level.SEVERE, null, ex); 86 | } 87 | 88 | return null; 89 | } 90 | 91 | /** 92 | * Returns the current state of the scanner. 93 | * @see TSLexerState 94 | * 95 | * @return the state of the scanner 96 | */ 97 | @Override 98 | public Object state() { 99 | return scanner.getState(); 100 | } 101 | 102 | @Override 103 | public void release() {} 104 | } 105 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/resources/templates/TSTemplateRTE.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Project: ${project.displayName} - ${project.name} 3 | * Version: 1.0.0 4 | * Date: ${date} ${time} 5 | * Author: ${user} 6 | * 7 | * Coded with Netbeans! 8 | */ 9 | 10 | # RTE_for_all_users 11 | setup.default.edit_RTE = 1 12 | 13 | RTE.default { 14 | # Markup_Options_(Word_cleanup_etc.) 15 | //enableWordClean = 1 16 | //removeTrailingBR = 1 17 | //removeComments = 1 18 | //removeTags = sdfield 19 | //blindImageOptions = magic,plain,dragdrop 20 | //disablePCexamples = 1 21 | //disableTYPO3Browsers = 1 22 | 23 | # Show_Hide_Color_Picker 24 | disableColorPicker = 1 25 | 26 | # Show_Hide_Statusbar_of_HTMLarea 27 | //showStatusBar = 0 28 | 29 | # Show_Hide_Table_Options_Buttons 30 | //hideTableOperationsInToolbar = 0 31 | 32 | # Options_for_Table_Editing_(cellspacing_cellpadding_border) 33 | //disableSpacingFieldsetInTableOperations = 0 34 | //disableAlignmentFieldsetInTableOperations = 0 35 | //disableColorFieldsetInTableOperations = 0 36 | //disableLayoutFieldsetInTableOperations = 0 37 | //disableBordersFieldsetInTableOperations = 0 38 | 39 | # Show_Hide_Buttons 40 | showButtons = formatblock, blockstyle, headline, textstylelabel, blockstylelabel, bold, italic, underline, unorderedlist, insertcharacter, link, image, removeformat, table, toggleborders, tableproperties, rowproperties, rowinsertabove, rowinsertunder, rowdelete, rowsplit, columninsertbefore, columninsertafter, columndelete, columnsplit, cellproperties, cellinsertbefore, cellinsertafter, celldelete, cellsplit, cellmerge, findreplace, insertcharacter, undo, redo, chMode, showhelp, 41 | hideButtons = fontstyle, fontsize, size, textstyle strikethrough,lefttoright, righttoleft, textindicator, emoticon, user, spellcheck, inserttag, outdent, indent, justifyfull, subscript, superscript, acronym, copy, cut, paste, about, textcolor, left, center, right, orderedlist, line; 42 | 43 | # Show_Hide_additional_Buttons 44 | //showButtons := addToList(textcolor, bgcolor, size, fontsize ) 45 | 46 | # Sorting_of_Buttons 47 | toolbarOrder = headline,textstyle,formatblock,blockstylelabel, blockstyle, bold, italic, underline, orderedlist, unorderedlist, findreplace, insertcharacter, undo, redo, showhelp, textstylelabel, image, link, line, table, toggleborders, tableproperties,rowproperties, rowinsertabove, rowinsertunder, rowdelete, rowsplit, columninsertbefore, columninsertafter, columndelete, columnsplit, cellproperties, cellinsertbefore, cellinsertafter, celldelete, cellsplit, cellmerge, textcolor,chMode,removeformat,about 48 | 49 | # Grouping_of_Buttons 50 | //keepButtonGroupTogether = 1 51 | //keepToggleBordersInToolbar = 1 52 | } 53 | 54 | 55 | # Setup_RTE 56 | RTE.default { 57 | # RTE_CSS_to_use 58 | contentCSS = fileadmin/templates/rte.css 59 | 60 | # Show_all_Classes 61 | showTagFreeClasses = 1 62 | 63 | # Overwrite_RTE_Styles_and_use_Custom_Styles 64 | ignoreMainStyleOverride = 1 65 | 66 | # Definitions_of_Classes_for_Anchors_Characters_Images_Paragraphs_Tables 67 | classesAnchor = YourClassname1, YourClassname2 68 | classesCharacter = YourClassname1, YourClassname2 69 | classesImage = YourClassname1, YourClassname2 70 | classesParagraph = YourClassname1, YourClassname2 71 | classesTable = YourClassname1, YourClassname2 72 | classesTR = YourClassname1, YourClassname2 73 | classesTH = YourClassname1, YourClassname2 74 | classesTD = YourClassname1, YourClassname2 75 | } 76 | 77 | 78 | # Allowed_span_Classes 79 | RTE.config.tt_content.bodytext.proc.allowedClasses = author 80 | 81 | 82 | RTE.default.proc { 83 | # Overwrite_TypoScript_Styles_and_use_Custom_Styles 84 | overruleMode = ts_css 85 | 86 | # Allowed_Denied_Tags 87 | allowTags = table, tbody, tr, th, td, h1, h2, h3, h4, h5, h6, div, p, br, span, ul, ol, li, re, blockquote, strong, em, b, i, u, sub, sup, strike, a, img, nobr, hr, tt, q, cite, abbr, acronym, center, bgcolor, bg, color, underline 88 | denyTags = font 89 | 90 | # Don't_convert_BR_to_P 91 | dontConvBRtoParagraph = 1 92 | 93 | # Allowed_outside_of_P_and_DIV 94 | allowTagsOutside = img,hr,center 95 | 96 | # Allowed_Attributes_of_P_and_DIV 97 | keepPDIVattribs = class,style,id 98 | } 99 | 100 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/nav/TSDeclarationFinder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.nav; 40 | 41 | import javax.swing.text.Document; 42 | import net.dfranek.typoscript.lexer.TSLexerUtils; 43 | import net.dfranek.typoscript.lexer.TSTokenId; 44 | import net.dfranek.typoscript.parser.TSParserResult; 45 | import net.dfranek.typoscript.parser.ast.TSASTNode; 46 | import org.netbeans.api.lexer.Token; 47 | import org.netbeans.api.lexer.TokenHierarchy; 48 | import org.netbeans.api.lexer.TokenSequence; 49 | import org.netbeans.modules.csl.api.DeclarationFinder; 50 | import org.netbeans.modules.csl.api.OffsetRange; 51 | import org.netbeans.modules.csl.spi.ParserResult; 52 | import org.openide.filesystems.FileObject; 53 | 54 | /** 55 | * 56 | * @author Daniel Franek 57 | */ 58 | public class TSDeclarationFinder implements DeclarationFinder { 59 | 60 | @Override 61 | public DeclarationLocation findDeclaration(ParserResult info, int caretOffset) { 62 | DeclarationLocation declLocation = DeclarationLocation.NONE; 63 | if (!(info instanceof TSParserResult)) return DeclarationLocation.NONE; 64 | TSParserResult result = (TSParserResult) info; 65 | 66 | TokenHierarchy th = result.getSnapshot().getTokenHierarchy(); 67 | TokenSequence ts = th.tokenSequence(TSTokenId.getLanguage()); 68 | TSASTNode tree = result.getTree(); 69 | ts.move(caretOffset); 70 | ts.moveNext(); 71 | Token token = ts.token(); 72 | TSASTNode item = tree.getChild(token.text().toString()); 73 | FileObject fo = result.getSnapshot().getSource().getFileObject(); 74 | if(fo != null && item != null) { 75 | declLocation = new DeclarationLocation(result.getSnapshot().getSource().getFileObject(), item.getOffset()); 76 | } 77 | 78 | return declLocation; 79 | } 80 | 81 | @Override 82 | public OffsetRange getReferenceSpan(final Document doc, final int caretOffset) { 83 | TokenSequence ts = TSLexerUtils.getTSTokenSequence(doc, caretOffset); 84 | ts.move(caretOffset); 85 | if (ts.moveNext()) { 86 | int offset = ts.offset(); 87 | Token token = ts.token(); 88 | TSTokenId id = token.id(); 89 | if(id.equals(TSTokenId.TS_PROPERTY)) { 90 | Token opVal = TSLexerUtils.findBwdNonSpace(ts); 91 | if ((opVal.id().equals(TSTokenId.TS_OPERATOR) && opVal.text().toString().equals("<"))) { 92 | return new OffsetRange(offset, offset + token.length()); 93 | } 94 | } 95 | } 96 | 97 | 98 | 99 | return OffsetRange.NONE; 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /test/unit/src/net/dfranek/typoscript/parser/TSTokenParserTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.parser; 40 | 41 | import java.io.File; 42 | import java.net.URISyntaxException; 43 | import junit.framework.TestCase; 44 | import net.dfranek.typoscript.lexer.TSLexerTestUtils; 45 | import net.dfranek.typoscript.lexer.TSTokenId; 46 | import net.dfranek.typoscript.parser.ast.TSASTNode; 47 | import net.dfranek.typoscript.parser.ast.TSASTNodeType; 48 | import org.netbeans.api.lexer.TokenSequence; 49 | 50 | /** 51 | * 52 | * @author Daniel 53 | */ 54 | public class TSTokenParserTest extends TestCase { 55 | 56 | public TSTokenParserTest(String name) { 57 | super(name); 58 | } 59 | 60 | public void testParser() throws URISyntaxException, Exception { 61 | TokenSequence ts = (TokenSequence) TSLexerTestUtils.seqForText(TSLexerTestUtils.getFileContent(new File(TSTokenParserTest.class.getResource("/net/dfranek/typoscript/parser/test.ts").toURI())), TSTokenId.getLanguage()); 62 | TSTokenParser tp = new TSTokenParser(ts); 63 | TSASTNode tree = tp.buildTree(); 64 | TSParserTestUtils.assertNodeEquals(tree.getChild("seite"), "seite", TSASTNodeType.PAGE, "", 7); 65 | TSParserTestUtils.assertNodeEquals(tree.getChild("seite").getChild("headerData"), "headerData", TSASTNodeType.UNKNOWN, "", 1); 66 | TSParserTestUtils.assertNodeEquals(tree.getChild("seite").getChild("headerData").getChild("10"), "10", TSASTNodeType.UNKNOWN, "", 1); 67 | TSParserTestUtils.assertNodeEquals(tree.getChild("seite").getChild("headerData").getChild("10").getChild("value"), "value", TSASTNodeType.VALUE, "test", 0); 68 | TSParserTestUtils.assertNodeEquals(tree.getChild("seite").getChild("config"), "config", TSASTNodeType.CONFIG, "", 1); 69 | TSParserTestUtils.assertNodeEquals(tree.getChild("seite").getChild("config").getChild("test"), "test", TSASTNodeType.VALUE, "129", 0); 70 | TSParserTestUtils.assertNodeEquals(tree.getChild("seite").getChild("test2"), "test2", TSASTNodeType.VALUE, "[10.w] + 16,19", 0); 71 | TSParserTestUtils.assertNodeEquals(tree.getChild("seite").getChild("test3"), "test3", TSASTNodeType.UNKNOWN, "", 1); 72 | TSParserTestUtils.assertNodeEquals(tree.getChild("seite").getChild("test3").getChild("test"), "test", TSASTNodeType.VALUE, "4", 0); 73 | TSParserTestUtils.assertNodeEquals(tree.getChild("seite").getChild("test4"), "test4", TSASTNodeType.VALUE, "3", 0); 74 | TSParserTestUtils.assertNodeEquals(tree.getChild("seite").getChild("test8"), "test8", TSASTNodeType.COPIED_PROPERTY, "seite.config.test", 0); 75 | TSParserTestUtils.assertNodeEquals(tree.getChild("seite").getChild("test5"), "test5", TSASTNodeType.VALUE, "asdasdasdasdasdsa", 0); 76 | 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/lexer/TSTokenId.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.lexer; 40 | 41 | import org.netbeans.api.lexer.Language; 42 | import org.netbeans.api.lexer.TokenId; 43 | 44 | /** 45 | * Enum with possible tokens for the TypoScript Language 46 | * 47 | * @author Daniel Franek 48 | */ 49 | public enum TSTokenId implements TokenId { 50 | 51 | TS_CURLY_OPEN(null, "brace"), 52 | TS_CURLY_CLOSE(null, "brace"), 53 | TS_COMMENT(null, "comment"), 54 | TS_MULTILINE_COMMENT(null, "comment"), 55 | TS_VALUE(null, "value"), 56 | TS_MULTILINE_VALUE(null, "value"), 57 | TS_PROPERTY(null, "ts"), 58 | TS_CONDITION(null, "condition"), 59 | TS_CONSTANT(null, "constant"), 60 | TS_STRING(null, "string"), 61 | TS_NUMBER(null, "number"), 62 | TS_REGEXP(null, "string"), 63 | TS_OPERATOR(null, "operator"), 64 | TS_KEYWORD(null, "keyword"), 65 | TS_RESERVED(null, "reserved"), 66 | TS_OBJECT(null, "keyword"), 67 | TS_FUNCTION(null, "keyword"), 68 | TS_EXTENSION(null, "extension"), 69 | TS_NL(null, "whitespace"), 70 | TS_PARANTHESE_OPEN(null, "brace"), 71 | TS_PARANTHESE_CLOSE(null, "brace"), 72 | WHITESPACE(null, "whitespace"), 73 | UNKNOWN_TOKEN(null, "error"); 74 | 75 | private final String primaryCategory; 76 | private final String fixedText; 77 | private static final Language language = new TSLanguageHierarchy().language(); 78 | private int start; 79 | private int end; 80 | 81 | TSTokenId(String fixedText, String primaryCategory) { 82 | this.fixedText = fixedText; 83 | this.primaryCategory = primaryCategory; 84 | } 85 | 86 | public static Language getLanguage() { 87 | return language; 88 | } 89 | 90 | @Override 91 | public String primaryCategory() { 92 | return primaryCategory; 93 | } 94 | 95 | /** 96 | * @return the start 97 | */ 98 | public int getStart() { 99 | return start; 100 | } 101 | 102 | /** 103 | * @param start the start to set 104 | */ 105 | public void setStart(int start) { 106 | this.start = start; 107 | } 108 | 109 | /** 110 | * @return the end 111 | */ 112 | public int getEnd() { 113 | return end; 114 | } 115 | 116 | /** 117 | * @param end the end to set 118 | */ 119 | public void setEnd(int end) { 120 | this.end = end; 121 | } 122 | 123 | /** Gets a LanguageDescription describing a set of token ids 124 | * that comprise the given language. 125 | * 126 | * @return non-null LanguageDescription 127 | */ 128 | public static Language language() { 129 | return language; 130 | } 131 | 132 | } 133 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/parser/ast/TSASTNode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.parser.ast; 40 | 41 | import java.util.Collection; 42 | import java.util.HashMap; 43 | 44 | /** 45 | * 46 | * @author Daniel Franek 47 | */ 48 | public class TSASTNode { 49 | private final String name; 50 | private String value; 51 | private TSASTNodeType type; 52 | private final HashMap children = new HashMap<>(); 53 | private TSASTNode parent; 54 | 55 | private final int length; 56 | private final int offset; 57 | private String suffix = ""; 58 | 59 | public TSASTNode(String name, String value, TSASTNodeType type, int offset, int length) { 60 | this.name = name; 61 | this.value = value; 62 | this.type = type; 63 | this.length = length; 64 | this.offset = offset; 65 | } 66 | 67 | public TSASTNode(String name, String value, TSASTNodeType type, int offset, int length, String suffix) { 68 | this.name = name; 69 | this.value = value; 70 | this.type = type; 71 | this.length = length; 72 | this.offset = offset; 73 | this.suffix = suffix; 74 | } 75 | 76 | /** 77 | * @return the name 78 | */ 79 | public String getName() { 80 | return name; 81 | } 82 | 83 | public void addChild(TSASTNode node) { 84 | node.setParent(this); 85 | children.put(node.getNodeName(), node); 86 | } 87 | 88 | public void removeChild(TSASTNode node) { 89 | children.remove(node.getName()); 90 | } 91 | 92 | public Collection getChildren() { 93 | return children.values(); 94 | } 95 | 96 | public boolean hasChild(TSASTNode node) { 97 | return children.containsKey(node.getName()); 98 | } 99 | 100 | public boolean hasChild(String name) { 101 | return children.containsKey(name); 102 | } 103 | 104 | public boolean hasChildren() { 105 | return !children.isEmpty(); 106 | } 107 | 108 | /** 109 | * @return the value 110 | */ 111 | public String getValue() { 112 | return value; 113 | } 114 | 115 | /** 116 | * @return the type 117 | */ 118 | public TSASTNodeType getType() { 119 | return type; 120 | } 121 | 122 | /** 123 | * @param value the value to set 124 | */ 125 | public void setValue(String value) { 126 | this.value = value; 127 | } 128 | 129 | /** 130 | * @param type the type to set 131 | */ 132 | public void setType(TSASTNodeType type) { 133 | this.type = type; 134 | } 135 | 136 | public void setParent(TSASTNode node) { 137 | this.parent = node; 138 | } 139 | 140 | public TSASTNode getParent() { 141 | return this.parent; 142 | } 143 | 144 | /** 145 | * @return the length 146 | */ 147 | public int getLength() { 148 | return length; 149 | } 150 | 151 | /** 152 | * @return the offset 153 | */ 154 | public int getOffset() { 155 | return offset; 156 | } 157 | 158 | public TSASTNode getChild(String name) { 159 | return children.get(name); 160 | } 161 | 162 | private String getNodeName() { 163 | return name + suffix; 164 | } 165 | 166 | public boolean isTypeSet() { 167 | return !(getType() == TSASTNodeType.UNKNOWN); 168 | } 169 | 170 | } 171 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/completion/TSCompletionItem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.completion; 40 | 41 | import java.util.Collections; 42 | import java.util.Set; 43 | import java.util.logging.Level; 44 | import java.util.logging.Logger; 45 | import javax.swing.ImageIcon; 46 | import org.netbeans.modules.csl.api.*; 47 | import org.openide.util.ImageUtilities; 48 | 49 | /** 50 | * 51 | * @author Daniel Franek 52 | */ 53 | public class TSCompletionItem implements CompletionProposal { 54 | 55 | private final int anchor; 56 | private final String name; 57 | private final ElementKind kind; 58 | private final String prefix; 59 | private static final Logger logger = Logger.getLogger(TSCodeCompletion.class.getName()); 60 | private final boolean smart; 61 | private String typeName; 62 | private final ElementHandle element; 63 | 64 | public TSCompletionItem(int anchor, String name, ElementKind kind, String prefix, boolean smart) { 65 | logger.setLevel(Level.ALL); 66 | this.anchor = anchor; 67 | this.name = name; 68 | this.kind = kind; 69 | this.prefix = prefix; 70 | this.smart = smart; 71 | this.element = new TSElement(name); 72 | } 73 | 74 | public TSCompletionItem(int anchor, String name, ElementKind kind, String prefix, boolean smart, String type) { 75 | logger.setLevel(Level.ALL); 76 | this.anchor = anchor; 77 | this.name = name; 78 | this.kind = kind; 79 | this.prefix = prefix; 80 | this.smart = smart; 81 | this.typeName = type; 82 | this.element = new TSElement(name); 83 | } 84 | 85 | public TSCompletionItem(int anchor, String name, ElementKind kind, String prefix, boolean smart, String type, String documentation) { 86 | logger.setLevel(Level.ALL); 87 | this.anchor = anchor; 88 | this.name = name; 89 | this.kind = kind; 90 | this.prefix = prefix; 91 | this.smart = smart; 92 | this.typeName = type; 93 | this.element = new TSElement(name, documentation); 94 | } 95 | 96 | @Override 97 | public int getAnchorOffset() { 98 | return anchor; 99 | } 100 | 101 | @Override 102 | public ElementHandle getElement() { 103 | return element; 104 | } 105 | 106 | @Override 107 | public String getName() { 108 | return this.name; 109 | } 110 | 111 | @Override 112 | public String getInsertPrefix() { 113 | String prefixL; 114 | final String insertPrefix = getName(); 115 | int indexOf = (this.prefix != null && insertPrefix != null) ? insertPrefix.toLowerCase().indexOf(this.prefix.toLowerCase()) : -1; 116 | prefixL = indexOf > 0 ? insertPrefix.substring(indexOf) : insertPrefix; 117 | logger.log(Level.FINEST, "insert Prefix for item {0} with completion prefix \"{1}\" :{2}", new Object[]{insertPrefix, this.prefix, prefixL}); 118 | return prefixL; 119 | } 120 | 121 | @Override 122 | public String getSortText() { 123 | return getName(); 124 | } 125 | 126 | @Override 127 | public String getLhsHtml(HtmlFormatter hf) { 128 | return getName(); 129 | } 130 | 131 | @Override 132 | public String getRhsHtml(HtmlFormatter hf) { 133 | return this.typeName == null ? this.kind.toString() : this.typeName; 134 | } 135 | 136 | @Override 137 | public ElementKind getKind() { 138 | return this.kind; 139 | } 140 | 141 | @Override 142 | public ImageIcon getIcon() { 143 | return new ImageIcon(ImageUtilities.loadImage("net/dfranek/typoscript/resources/ts.png")); 144 | } 145 | 146 | @Override 147 | public Set getModifiers() { 148 | return Collections.emptySet(); 149 | } 150 | 151 | @Override 152 | public boolean isSmart() { 153 | return smart; 154 | } 155 | 156 | @Override 157 | public int getSortPrioOverride() { 158 | return 0; 159 | } 160 | 161 | @Override 162 | public String getCustomInsertTemplate() { 163 | return getName(); 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/parser/TSParserUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.parser; 40 | 41 | import java.util.List; 42 | import javax.swing.text.BadLocationException; 43 | import net.dfranek.typoscript.lexer.TSLexerUtils; 44 | import net.dfranek.typoscript.lexer.TSTokenId; 45 | import net.dfranek.typoscript.parser.ast.TSASTNode; 46 | import org.netbeans.api.lexer.Token; 47 | import org.netbeans.api.lexer.TokenSequence; 48 | import org.netbeans.editor.BaseDocument; 49 | import org.netbeans.editor.Utilities; 50 | 51 | /** 52 | * 53 | * @author Daniel Franek 54 | */ 55 | public class TSParserUtils { 56 | 57 | public static int findHierarchyStart(TokenSequence ts, int caretOffset) { 58 | ts.move(caretOffset); 59 | ts.moveNext(); 60 | ts.movePrevious(); 61 | Token t = ts.token(); 62 | // causes an error if care is at the end of a token -> move back 63 | if (ts.offset() + t.length() == caretOffset && !t.id().equals(TSTokenId.TS_NL)) { 64 | ts.movePrevious(); 65 | t = ts.token(); 66 | } 67 | while (!TSLexerUtils.tokenIsKeyword(t.id()) && !t.id().equals(TSTokenId.TS_NL) && ts.movePrevious()) { 68 | t = ts.token(); 69 | } 70 | 71 | if (t.id().equals(TSTokenId.TS_NL)) { 72 | int balance = 0; 73 | ts.movePrevious(); 74 | 75 | do { 76 | if (balance > 0 && t.id().equals(TSTokenId.TS_CURLY_OPEN)) { 77 | balance--; 78 | } 79 | t = ts.token(); 80 | if (t.id().equals(TSTokenId.TS_CURLY_CLOSE)) { 81 | balance++; 82 | } 83 | } while (ts.movePrevious() && (!t.id().equals(TSTokenId.TS_CURLY_OPEN) || balance != 0)); 84 | 85 | t = ts.token(); 86 | while (t.id().equals(TSTokenId.WHITESPACE) && ts.movePrevious()) { 87 | t = ts.token(); 88 | } 89 | } 90 | return ts.offset(); 91 | } 92 | 93 | public static List> getCurrentHierarchy(int caretOffset, BaseDocument doc, TokenSequence ts, TSASTNode tree, List> h) throws BadLocationException { 94 | if (caretOffset == 0) { 95 | return h; 96 | } 97 | int lineStart = Utilities.getRowFirstNonWhite(doc, caretOffset); 98 | ts.move(caretOffset); 99 | ts.moveNext(); 100 | Token token = ts.token(); 101 | if (token == null) { 102 | ts.movePrevious(); 103 | token = ts.token(); 104 | } 105 | 106 | if (token.text().toString().equals(".")) { 107 | ts.movePrevious(); 108 | token = ts.token(); 109 | } 110 | 111 | if (TSLexerUtils.tokenIsKeyword(token.id())) { 112 | h.add(token); 113 | } 114 | while (ts.offset() > lineStart) { 115 | ts.movePrevious(); 116 | token = ts.token(); 117 | if (token.id().equals(TSTokenId.TS_OPERATOR) && token.text().toString().equals("<")) { 118 | return h; 119 | } 120 | if (TSLexerUtils.tokenIsKeyword(token.id())) { 121 | h.add(token); 122 | } 123 | } 124 | if (tree.getChild(token.text().toString()) != null && getCurlyBalance(ts) == 0) { 125 | return h; 126 | } else { 127 | ts.movePrevious(); 128 | do { 129 | token = ts.token(); 130 | } while (!token.id().equals(TSTokenId.TS_CURLY_OPEN) && ts.movePrevious()); 131 | ts.movePrevious(); 132 | token = ts.token(); 133 | while (token.id().equals(TSTokenId.WHITESPACE) && ts.movePrevious()) { 134 | token = ts.token(); 135 | } 136 | 137 | if (tree.getChild(token.text().toString()) != null && getCurlyBalance(ts) == 0) { 138 | h.add(token); 139 | return h; 140 | } else { 141 | return getCurrentHierarchy(ts.offset(), doc, ts, tree, h); 142 | } 143 | } 144 | } 145 | 146 | private static int getCurlyBalance(TokenSequence ts) { 147 | int balance = 0; 148 | int curOffset = ts.offset(); 149 | Token t; 150 | while (ts.movePrevious()) { 151 | t = ts.token(); 152 | if (t.id().equals(TSTokenId.TS_CURLY_OPEN)) { 153 | balance--; 154 | } 155 | if (t.id().equals(TSTokenId.TS_CURLY_CLOSE)) { 156 | balance++; 157 | } 158 | } 159 | ts.move(curOffset); 160 | ts.movePrevious(); 161 | 162 | return balance; 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/parser/ast/TSASTNodeType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.parser.ast; 40 | 41 | import java.util.Arrays; 42 | import java.util.List; 43 | 44 | /** 45 | * 46 | * @author Daniel Franek 47 | */ 48 | public enum TSASTNodeType { 49 | 50 | // Top Level Objects 51 | PLUGIN, 52 | CONFIG, 53 | CONSTANTS, 54 | PAGE, 55 | FE_DATA, 56 | FE_TABLE, 57 | FRAMESET, 58 | FRAME, 59 | META, 60 | CARRAY, 61 | 62 | // Graphic Functions 63 | GIFBUILDER, 64 | GIFBUILDER_TEXT("TEXT"), 65 | GIFBUILDER_IMAGE("IMAGE"), 66 | SHADOW, 67 | EMBOSS, 68 | OUTLINE, 69 | BOX, 70 | EFFECT, 71 | WORKAREA, 72 | CROP, 73 | SCALE, 74 | ADJUST, 75 | IMGMAP, 76 | 77 | // Menu Objects 78 | GMENU, 79 | GMENU_LAYERS, 80 | TMENU, 81 | TMENU_LAYERS, 82 | GMENU_FOLDOUT, 83 | TMENUITEM, 84 | TMENUITEM_LOGIC("TMENUITEM"), 85 | IMGMENU, 86 | IMGMENUITEM, 87 | JSMENU, 88 | JSMENUITEM, 89 | 90 | // Content Objects 91 | HTML, 92 | TEXT, 93 | COBJ_ARRAY, 94 | COA, 95 | COA_INT, 96 | FILE, 97 | IMAGE, 98 | IMG_RESOURCE, 99 | CLEARGIF, 100 | CONTENT, 101 | RECORDS, 102 | HMENU, 103 | CTABLE, 104 | OTABLE, 105 | COLUMNS, 106 | HRULER, 107 | IMGTEXT, 108 | CASE, 109 | LOAD_REGISTER, 110 | RESTORE_REGISTER, 111 | FORM, 112 | SEARCHRESULT, 113 | USER, 114 | USER_INT, 115 | PHP_SCRIPT, 116 | PHP_SCRIPT_INT, 117 | PHP_SCRIPT_EXT, 118 | TEMPLATE, 119 | MULTIMEDIA, 120 | EDITPANEL, 121 | STDWRAP("stdWrap"), 122 | 123 | // Relevant for Parsing 124 | UNKNOWN, 125 | VALUE, 126 | LOGIC_PROPERTY("if"), 127 | ROOTLEVEL, 128 | COPIED_PROPERTY, 129 | CLEARED_PROPERY, 130 | CONDITION, 131 | WRAP(""); 132 | 133 | TSASTNodeType() { 134 | typeName = this.name(); 135 | } 136 | 137 | TSASTNodeType(String name) { 138 | typeName = name; 139 | } 140 | 141 | @Override 142 | public String toString() { 143 | return typeName; 144 | } 145 | protected String typeName; 146 | 147 | public static TSASTNodeType getNodeTypeForObject(String name) { 148 | if (name.equals("config")) { 149 | return CONFIG; 150 | } 151 | if (name.equals("stdWrap") || name.equals("stdWrap2") || name.equals("allStdWrap")) { 152 | return STDWRAP; 153 | } 154 | 155 | List t = Arrays.asList(new String[]{"allWrap", "beforeWrap", "commentWrap", "dontWrapInTable", "imageLinkWrap", "ATagBeforeWrap", "encapsLinesStdWrap", "tagStdWrap", "tableStdWrap", "fieldWrap", "labelStdWrap", "labelWrap", "linkWrap", "wrapNonWrappedLines", "nonTypoTagStdWrap", "nonWrappedTag", "plainTextStdWrap", "dataWrap", "innerWrap", "innerWrap2", "noTrimWrap", "outerWrap", "wrap", "wrap1", "wrap2", "wrap3", "wrapAfterTags", "wrapAlign", "wrapFieldName", "wrapItemAndSub", "wrapNonWrappedLines", "wraps", "wrapSplitChar", "radioWrap", "radioInputWrap", "accessibilityWrap", "noWrapAttr"}); 156 | if (t.contains(name)) { 157 | return WRAP; 158 | } 159 | 160 | if (name.equals("if") || name.equals("ifBlank") || name.equals("ifEmpty")) { 161 | return TSASTNodeType.LOGIC_PROPERTY; 162 | } 163 | 164 | t = Arrays.asList(new String[]{"ACT", "NO", "RO", "CUR", "USR", "SPC", "ACTRO", "USERDEF1RO", "USERDEF2RO", "USERDEF1", "USERDEF2","CURRO"}); 165 | if (t.contains(name)) { 166 | return TMENUITEM; 167 | } 168 | 169 | t = Arrays.asList(new String[]{"IFSUB","IFSUBRO", "ACTIFSUB", "ACTIFSUBRO", "CURIFSUB", "CURIFSUBRO"}); 170 | if (t.contains(name)) { 171 | return TMENUITEM_LOGIC; 172 | } 173 | for (TSASTNodeType type : TSASTNodeType.values()) { 174 | if (type.name().equals(name)) { 175 | return type; 176 | } 177 | } 178 | return TSASTNodeType.UNKNOWN; 179 | } 180 | 181 | public static TSASTNodeType getNodeTypeForObject(String name, TSASTNode actNode) { 182 | for (TSASTNodeType type : TSASTNodeType.values()) { 183 | if (type.name().equals(name)) { 184 | if (actNode.getType() == TSASTNodeType.GIFBUILDER && type.name().equals("IMAGE")) { 185 | return GIFBUILDER_IMAGE; 186 | } 187 | if (actNode.getType() == TSASTNodeType.GIFBUILDER && type.name().equals("TEXT")) { 188 | return GIFBUILDER_TEXT; 189 | } 190 | return type; 191 | } 192 | } 193 | return getNodeTypeForObject(name); 194 | } 195 | 196 | public String getTypeString() { 197 | return this.name(); 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/typinghooks/TSTypedTextInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2013 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.typinghooks; 40 | 41 | import javax.swing.text.BadLocationException; 42 | import javax.swing.text.Document; 43 | import net.dfranek.typoscript.TSLanguage; 44 | import net.dfranek.typoscript.lexer.TSLexerUtils; 45 | import net.dfranek.typoscript.lexer.TSTokenId; 46 | import org.netbeans.api.editor.mimelookup.MimePath; 47 | import org.netbeans.api.editor.mimelookup.MimeRegistration; 48 | import org.netbeans.api.lexer.Token; 49 | import org.netbeans.api.lexer.TokenId; 50 | import org.netbeans.api.lexer.TokenSequence; 51 | import org.netbeans.editor.BaseDocument; 52 | import org.netbeans.spi.editor.typinghooks.TypedTextInterceptor; 53 | 54 | /** 55 | * 56 | * @author Daniel Franek 57 | */ 58 | public class TSTypedTextInterceptor implements TypedTextInterceptor { 59 | 60 | @Override 61 | public boolean beforeInsert(Context cntxt) throws BadLocationException { 62 | return false; 63 | } 64 | 65 | @Override 66 | public void insert(MutableContext context) throws BadLocationException { 67 | Document document = context.getDocument(); 68 | BaseDocument doc = (BaseDocument) document; 69 | int caretOffset = context.getOffset(); 70 | char ch = context.getText().charAt(0); 71 | if (doNotAutoComplete(ch) || caretOffset == 0) { 72 | return; 73 | } 74 | String selection = context.getReplacedText(); 75 | if (selection != null && selection.length() > 0) { 76 | if ((ch == '[' || ch == '{')) { 77 | char firstChar = selection.charAt(0); 78 | if (firstChar != ch) { 79 | 80 | int lastChar = selection.charAt(selection.length() - 1); 81 | // Replace the surround-with chars? 82 | if (selection.length() > 1 83 | && ((firstChar == '"' || firstChar == '\'' || firstChar == '(' 84 | || firstChar == '{' || firstChar == '[') 85 | && lastChar == matching(firstChar))) { 86 | String innerText = selection.substring(1, selection.length() - 1); 87 | String text = Character.toString(ch) + innerText + Character.toString(matching(ch)); 88 | context.setText(text, text.length()); 89 | } else { 90 | String text = ch + selection + matching(ch); 91 | context.setText(text, text.length()); 92 | } 93 | } 94 | } 95 | } 96 | if (ch == '[') { 97 | completeOpeningBracket(context, ch); 98 | } 99 | } 100 | 101 | private boolean doNotAutoComplete(final char ch) { 102 | return (ch != '[' && ch != '{'); 103 | } 104 | 105 | /** 106 | * Returns for an opening bracket or quote the appropriate closing 107 | * character. 108 | */ 109 | private char matching(char bracket) { 110 | switch (bracket) { 111 | case '(': 112 | return ')'; 113 | case '/': 114 | return '/'; 115 | case '[': 116 | return ']'; 117 | case '\"': 118 | return '\"'; // NOI18N 119 | case '\'': 120 | return '\''; 121 | case '{': 122 | return '}'; 123 | case '}': 124 | return '{'; 125 | default: 126 | return bracket; 127 | } 128 | } 129 | 130 | /** 131 | * Check for various conditions and possibly add a pairing bracket to the 132 | * already inserted. 133 | * 134 | * @param doc the document 135 | * @param dotPos position of the opening bracket (already in the doc) 136 | * @param caret caret 137 | * @param bracket the bracket that was inserted 138 | */ 139 | private void completeOpeningBracket(MutableContext context, char bracket) throws BadLocationException { 140 | if(completeBracket(context)) { 141 | StringBuilder sb = new StringBuilder(); 142 | sb.append(bracket); 143 | sb.append(matching(bracket)); 144 | context.setText(sb.toString(), 1); 145 | } 146 | } 147 | 148 | private boolean completeBracket(MutableContext context) { 149 | int offset = context.getOffset(); 150 | final BaseDocument doc = (BaseDocument) context.getDocument(); 151 | TokenSequence ts = TSLexerUtils.getTSTokenSequence(doc, offset); 152 | if (ts == null) { 153 | return true; 154 | } 155 | ts.move(offset); 156 | if (!ts.moveNext() && !ts.movePrevious()) { 157 | return true; 158 | } 159 | Token token = ts.token(); 160 | TokenId id = token.id(); 161 | 162 | return id != TSTokenId.TS_CURLY_OPEN; 163 | } 164 | 165 | @Override 166 | public void afterInsert(Context cntxt) throws BadLocationException { 167 | // deliberatly empty 168 | } 169 | 170 | @Override 171 | public void cancelled(Context cntxt) { 172 | // deliberatly empty 173 | } 174 | 175 | @MimeRegistration(mimeType = TSLanguage.TS_MIME_TYPE, service = TypedTextInterceptor.Factory.class) 176 | public static class Factory implements TypedTextInterceptor.Factory { 177 | 178 | @Override 179 | public TypedTextInterceptor createTypedTextInterceptor(MimePath mimePath) { 180 | return new TSTypedTextInterceptor(); 181 | } 182 | } 183 | 184 | } 185 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/indent/TSBracesMatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.indent; 40 | 41 | import javax.swing.text.AbstractDocument; 42 | import javax.swing.text.BadLocationException; 43 | import net.dfranek.typoscript.lexer.TSLexerUtils; 44 | import net.dfranek.typoscript.lexer.TSTokenId; 45 | import org.netbeans.api.lexer.Token; 46 | import org.netbeans.api.lexer.TokenId; 47 | import org.netbeans.api.lexer.TokenSequence; 48 | import org.netbeans.editor.BaseDocument; 49 | import org.netbeans.modules.csl.api.OffsetRange; 50 | import org.netbeans.spi.editor.bracesmatching.BracesMatcher; 51 | import org.netbeans.spi.editor.bracesmatching.MatcherContext; 52 | 53 | /** 54 | * 55 | * @author Daniel Franek 56 | */ 57 | public class TSBracesMatcher implements BracesMatcher { 58 | 59 | MatcherContext context; 60 | 61 | TSBracesMatcher(MatcherContext mc) { 62 | context = mc; 63 | } 64 | 65 | @Override 66 | public int[] findOrigin() throws InterruptedException, BadLocationException { 67 | ((AbstractDocument) context.getDocument()).readLock(); 68 | try { 69 | BaseDocument doc = (BaseDocument) context.getDocument(); 70 | int offset = context.getSearchOffset(); 71 | 72 | TokenSequence ts = TSLexerUtils.getTSTokenSequence(doc, offset); 73 | 74 | if (ts != null) { 75 | ts.move(offset); 76 | 77 | if (!ts.moveNext()) { 78 | return null; 79 | } 80 | 81 | Token token = ts.token(); 82 | 83 | if (token == null) { 84 | return null; 85 | } 86 | 87 | TokenId id = token.id(); 88 | 89 | if (TSLexerUtils.textEquals(token.text(), '(')) { 90 | return new int [] { ts.offset(), ts.offset() + token.length() }; 91 | } else if (TSLexerUtils.textEquals(token.text(), ')')) { 92 | return new int [] { ts.offset(), ts.offset() + token.length() }; 93 | } else if (id == TSTokenId.TS_CURLY_OPEN) { 94 | return new int [] { ts.offset(), ts.offset() + token.length() }; 95 | } else if (id == TSTokenId.TS_CURLY_CLOSE) { 96 | return new int [] { ts.offset(), ts.offset() + token.length() }; 97 | } else if (TSLexerUtils.textEquals(token.text(), '[')) { 98 | return new int [] { ts.offset(), ts.offset() + token.length() }; 99 | } else if (TSLexerUtils.textEquals(token.text(), ']')) { 100 | return new int [] { ts.offset(), ts.offset() + token.length() }; 101 | } 102 | 103 | } 104 | return null; 105 | } finally { 106 | ((AbstractDocument) context.getDocument()).readUnlock(); 107 | } 108 | } 109 | 110 | @Override 111 | public int[] findMatches() throws InterruptedException, BadLocationException { 112 | ((AbstractDocument) context.getDocument()).readLock(); 113 | try { 114 | BaseDocument doc = (BaseDocument) context.getDocument(); 115 | int offset = context.getSearchOffset(); 116 | 117 | TokenSequence ts = TSLexerUtils.getTSTokenSequence(doc, offset); 118 | 119 | if (ts != null) { 120 | ts.move(offset); 121 | 122 | if (!ts.moveNext()) { 123 | return null; 124 | } 125 | 126 | Token token = ts.token(); 127 | 128 | if (token == null) { 129 | return null; 130 | } 131 | 132 | TokenId id = token.id(); 133 | 134 | OffsetRange r; 135 | if (TSLexerUtils.textEquals(token.text(), '(')) { 136 | r = TSLexerUtils.findFwd(ts, TSTokenId.TS_PARANTHESE_OPEN, '(', TSTokenId.TS_PARANTHESE_CLOSE, ')'); 137 | return new int [] {r.getStart(), r.getEnd() }; 138 | } else if (TSLexerUtils.textEquals(token.text(), ')')) { 139 | r = TSLexerUtils.findBwd(ts, TSTokenId.TS_PARANTHESE_OPEN, '(', TSTokenId.TS_PARANTHESE_CLOSE, ')'); 140 | return new int [] {r.getStart(), r.getEnd() }; 141 | } else if (id == TSTokenId.TS_CURLY_OPEN) { 142 | r= TSLexerUtils.findFwd(ts, TSTokenId.TS_CURLY_OPEN ,'{', TSTokenId.TS_CURLY_CLOSE, '}'); 143 | return new int [] {r.getStart(), r.getEnd() }; 144 | } else if (id == TSTokenId.TS_CURLY_CLOSE) { 145 | r = TSLexerUtils.findBwd(ts, TSTokenId.TS_CURLY_OPEN, '{', TSTokenId.TS_CURLY_CLOSE, '}'); 146 | return new int [] {r.getStart(), r.getEnd() }; 147 | } else if (TSLexerUtils.textEquals(token.text(), '[')) { 148 | r = TSLexerUtils.findFwd(ts, TSTokenId.TS_OPERATOR, '[', TSTokenId.TS_OPERATOR, ']'); 149 | return new int [] {r.getStart(), r.getEnd() }; 150 | } else if (TSLexerUtils.textEquals(token.text(), ']')) { 151 | r = TSLexerUtils.findBwd(ts, TSTokenId.TS_OPERATOR, '[', TSTokenId.TS_OPERATOR, ']'); 152 | return new int [] {r.getStart(), r.getEnd() }; 153 | } 154 | } 155 | return null; 156 | } finally { 157 | ((AbstractDocument) context.getDocument()).readUnlock(); 158 | } 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /test/unit/src/net/dfranek/typoscript/lexer/TSLexerTestUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.lexer; 40 | 41 | import java.io.BufferedReader; 42 | import java.io.File; 43 | import java.io.FileInputStream; 44 | import java.io.InputStreamReader; 45 | import junit.framework.TestCase; 46 | import org.netbeans.api.lexer.*; 47 | import org.netbeans.lib.lexer.LexerUtilsConstants; 48 | 49 | /** 50 | * 51 | * @author Daniel Franek 52 | * 53 | * parts of the code are from LexerTestUtilities (org.netbeans.lib.lexer.test) 54 | */ 55 | public class TSLexerTestUtils extends TestCase{ 56 | 57 | public static TokenSequence seqForText(String text, Language language) { 58 | TokenHierarchy hi = TokenHierarchy.create(text, language); 59 | return hi.tokenSequence(language); 60 | } 61 | 62 | public static void next(TokenSequence ts, TokenId id, String fixedText) { 63 | assertTrue(ts.moveNext()); 64 | TSLexerTestUtils.assertTokenEquals("Token index[" + ts.index() + "]", ts, id, fixedText, -1); 65 | } 66 | 67 | /** 68 | * Compare TokenSequence.token() to the given 69 | * token id, text and offset. 70 | * 71 | * @param message 72 | * @param ts 73 | * @param id 74 | * @param text 75 | * @param offset expected offset. It may be -1 to prevent offset testing. 76 | */ 77 | public static void assertTokenEquals(String message, TokenSequence ts, TokenId id, String text, int offset) { 78 | message = messagePrefix(message); 79 | Token t = ts.token(); 80 | TestCase.assertNotNull("Token is null", t); 81 | TokenId tId = t.id(); 82 | TestCase.assertEquals(message + "Invalid token.id() for text=\"" + debugTextOrNull(t.text()) + '"', id, tId); 83 | CharSequence tText = t.text(); 84 | assertTextEquals(message + "Invalid token.text() for id=" + LexerUtilsConstants.idToString(id), text, tText); 85 | // The token's length must correspond to text.length() 86 | TestCase.assertEquals(message + "Invalid token.length()", text.length(), t.length()); 87 | 88 | if (offset != -1) { 89 | int tsOffset = ts.offset(); 90 | TestCase.assertEquals(message + "Invalid tokenSequence.offset()", offset, tsOffset); 91 | 92 | // It should also be true that if the token is non-flyweight then 93 | // ts.offset() == t.offset() 94 | // and if it's flyweight then t.offset() == -1 95 | int tOffset = t.offset(null); 96 | assertTokenOffsetMinusOneForFlyweight(t.isFlyweight(), tOffset); 97 | if (!t.isFlyweight()) { 98 | assertTokenOffsetsEqual(message, tOffset, offset); 99 | } 100 | } 101 | } 102 | 103 | private static String messagePrefix(String message) { 104 | if (message != null) { 105 | message = message + ": "; 106 | } else { 107 | message = ""; 108 | } 109 | return message; 110 | } 111 | 112 | /** 113 | * Return the given text as String 114 | * translating the special characters (and '\') into escape sequences. 115 | * 116 | * @param text non-null text to be debugged. 117 | * @return non-null string containing the debug text or "null". 118 | */ 119 | public static String debugTextOrNull(CharSequence text) { 120 | return (text != null) ? debugText(text) : ""; 121 | } 122 | 123 | public static void assertTextEquals(String message, CharSequence expected, CharSequence actual) { 124 | if (!textEquals(expected, actual)) { 125 | TestCase.fail(messagePrefix(message) + 126 | " expected:\"" + expected + "\" but was:\"" + actual + "\""); 127 | } 128 | } 129 | 130 | /** 131 | * Return the given text as String 132 | * translating the special characters (and '\') into escape sequences. 133 | * 134 | * @param text non-null text to be debugged. 135 | * @return non-null string containing the debug text. 136 | */ 137 | public static String debugText(CharSequence text) { 138 | return TokenUtilities.debugText(text); 139 | } 140 | 141 | /** 142 | * Compare whether the two character sequences represent the same text. 143 | * @param text1 144 | * @param text2 145 | * @return 146 | */ 147 | public static boolean textEquals(CharSequence text1, CharSequence text2) { 148 | return TokenUtilities.equals(text1, text2); 149 | } 150 | 151 | private static void assertTokenOffsetMinusOneForFlyweight(boolean tokenFlyweight, int offset) { 152 | if (tokenFlyweight) { 153 | TestCase.assertEquals("Flyweight token => token.offset()=-1", -1, offset); 154 | } else { // non-flyweight 155 | TestCase.assertTrue("Non-flyweight token => token.offset()!=-1 but " + offset, (offset != -1)); 156 | } 157 | } 158 | 159 | public static void assertTokenOffsetsEqual(String message, int offset1, int offset2) { 160 | if (offset1 != -1 && offset2 != -1) { // both non-flyweight 161 | TestCase.assertEquals(messagePrefix(message) 162 | + "Offsets equal", offset1, offset2); 163 | } 164 | } 165 | 166 | public static String getFileContent (File file) throws Exception{ 167 | StringBuilder sb = new StringBuilder(); 168 | String lineSep = "\n";//NOI18N 169 | try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"))) { 170 | String line = br.readLine(); 171 | while (line != null) { 172 | sb.append(line); 173 | sb.append(lineSep); 174 | line = br.readLine(); 175 | } 176 | } 177 | return sb.toString(); 178 | } 179 | 180 | } 181 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/TSLanguage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript; 40 | 41 | import static net.dfranek.typoscript.TSLanguage.TS_MIME_TYPE; 42 | import net.dfranek.typoscript.completion.TSCodeCompletion; 43 | import net.dfranek.typoscript.lexer.TSTokenId; 44 | import net.dfranek.typoscript.nav.TSDeclarationFinder; 45 | import net.dfranek.typoscript.parser.TSParser; 46 | import net.dfranek.typoscript.parser.TSStructureScanner; 47 | import org.netbeans.api.lexer.Language; 48 | import org.netbeans.api.templates.TemplateRegistration; 49 | import org.netbeans.api.templates.TemplateRegistrations; 50 | import org.netbeans.core.spi.multiview.MultiViewElement; 51 | import org.netbeans.core.spi.multiview.text.MultiViewEditorElement; 52 | import org.netbeans.modules.csl.api.CodeCompletionHandler; 53 | import org.netbeans.modules.csl.api.DeclarationFinder; 54 | import org.netbeans.modules.csl.api.StructureScanner; 55 | import org.netbeans.modules.csl.spi.DefaultLanguageConfig; 56 | import org.netbeans.modules.csl.spi.LanguageRegistration; 57 | import org.netbeans.modules.parsing.spi.Parser; 58 | import org.netbeans.modules.parsing.spi.indexing.PathRecognizerRegistration; 59 | import org.openide.WizardDescriptor; 60 | import org.openide.awt.ActionID; 61 | import org.openide.awt.ActionReference; 62 | import org.openide.awt.ActionReferences; 63 | import org.openide.filesystems.MIMEResolver; 64 | import org.openide.util.Lookup; 65 | import org.openide.windows.TopComponent; 66 | 67 | /** 68 | * 69 | * @author Daniel Franek 70 | */ 71 | 72 | @LanguageRegistration(mimeType=TSLanguage.TS_MIME_TYPE, useMultiview = true) 73 | @PathRecognizerRegistration(mimeTypes = TSLanguage.TS_MIME_TYPE, libraryPathIds = {}, binaryLibraryPathIds = {}) //NOI18N 74 | @ActionReferences({ 75 | @ActionReference( 76 | path = "Loaders/text/x-typoscript/Actions", 77 | id = @ActionID(category = "System", id = "org.openide.actions.PropertiesAction"), 78 | position = 100, 79 | separatorAfter = 200 80 | ), 81 | @ActionReference( 82 | path = "Loaders/text/x-typoscript/Actions", 83 | id = @ActionID(category = "Edit", id = "org.openide.actions.DeleteAction"), 84 | position = 300 85 | ), 86 | @ActionReference( 87 | path = "Loaders/text/x-typoscript/Actions", 88 | id = @ActionID(category = "Edit", id = "org.openide.actions.CopyAction"), 89 | position = 400, 90 | separatorAfter = 500 91 | ), 92 | @ActionReference( 93 | path = "Loaders/text/x-typoscript/Actions", 94 | id = @ActionID(category = "System", id = "org.openide.actions.FileSystemAction"), 95 | position = 600 96 | ), 97 | @ActionReference( 98 | path = "Loaders/text/x-typoscript/Actions", 99 | id = @ActionID(category = "System", id = "org.openide.actions.SaveAsTemplateAction"), 100 | position = 700, 101 | separatorAfter = 800 102 | ), 103 | @ActionReference( 104 | path = "Loaders/text/x-typoscript/Actions", 105 | id = @ActionID(category = "System", id = "org.openide.actions.ToolsAction"), 106 | position = 900, 107 | separatorAfter = 1000 108 | ), 109 | @ActionReference( 110 | path = "Loaders/text/x-typoscript/Actions", 111 | id = @ActionID(category = "System", id = "org.openide.actions.OpenAction"), 112 | position = 1100, 113 | separatorAfter = 1200 114 | ), 115 | @ActionReference( 116 | path = "Loaders/text/x-typoscript/Actions", 117 | id = @ActionID(category = "System", id = "org.openide.actions.RenameAction"), 118 | position = 1400 119 | ), 120 | }) 121 | @MIMEResolver.Registration( 122 | displayName = "#text/x-typoscript", 123 | resource = "resources/TSResolver.xml" 124 | ) 125 | public class TSLanguage extends DefaultLanguageConfig { 126 | 127 | private static final String LINE_COMMENT_PREFIX = "#";//NOI18N 128 | public static final String TS_MIME_TYPE = "text/x-typoscript";//NOI18N 129 | 130 | @MultiViewElement.Registration( 131 | displayName="#LBL_TSEditorTab", 132 | iconBase="net/dfranek/typoscript/resources/ts_file_16.png", 133 | persistenceType=TopComponent.PERSISTENCE_ONLY_OPENED, 134 | preferredID="ts.source", 135 | mimeType=TS_MIME_TYPE, 136 | position=1 137 | ) 138 | public static MultiViewEditorElement createMultiViewEditorElement(Lookup context) { 139 | return new MultiViewEditorElement(context); 140 | } 141 | 142 | @TemplateRegistrations({ 143 | @TemplateRegistration(folder = "TypoScript", content = "resources/templates/TSTemplate.ts", description = "resources/templates/TSTemplate.html", displayName = "#Templates/TypoScript/TSTemplate.ts", scriptEngine = "freemarker"), 144 | @TemplateRegistration(folder = "TypoScript", content = "resources/templates/TSTemplateComments.ts", description = "resources/templates/TSTemplateComments.html", displayName = "#Templates/TypoScript/TSTemplateComments.ts", scriptEngine = "freemarker"), 145 | @TemplateRegistration(folder = "TypoScript", content = "resources/templates/TSTemplateHTML5Advanced.ts", description = "resources/templates/TSTemplateHTML5Advanced.html", displayName = "#Templates/TypoScript/TSTemplateHTML5Advanced.ts", scriptEngine = "freemarker"), 146 | @TemplateRegistration(folder = "TypoScript", content = "resources/templates/TSTemplateHTML5Multilingual.ts", description = "resources/templates/TSTemplateHTML5Multilingual.html", displayName = "#Templates/TypoScript/TSTemplateHTML5Multilingual.ts", scriptEngine = "freemarker"), 147 | @TemplateRegistration(folder = "TypoScript", content = "resources/templates/TSTemplateRTE.ts", description = "resources/templates/TSTemplateRTE.html", displayName = "#Templates/TypoScript/TSTemplateRTE.ts", scriptEngine = "freemarker") 148 | }) 149 | @SuppressWarnings("rawtypes") 150 | public static WizardDescriptor.InstantiatingIterator templateIterator() { 151 | return null; 152 | } 153 | 154 | @Override 155 | public Language getLexerLanguage() { 156 | return TSTokenId.getLanguage(); 157 | } 158 | 159 | @Override 160 | public String getDisplayName() { 161 | return "TypoScript"; 162 | } 163 | 164 | @Override 165 | public String getLineCommentPrefix() { 166 | return LINE_COMMENT_PREFIX; 167 | } 168 | 169 | @Override 170 | public String getPreferredExtension() { 171 | return "ts"; 172 | } 173 | 174 | 175 | @Override 176 | public boolean isIdentifierChar(char c) { 177 | return Character.isJavaIdentifierPart(c); 178 | } 179 | 180 | @Override 181 | public CodeCompletionHandler getCompletionHandler() { 182 | return new TSCodeCompletion(); 183 | } 184 | 185 | @Override 186 | public Parser getParser() { 187 | return new TSParser(); 188 | } 189 | 190 | @Override 191 | public boolean hasStructureScanner() { 192 | return true; 193 | } 194 | 195 | @Override 196 | public StructureScanner getStructureScanner() { 197 | return new TSStructureScanner(); 198 | } 199 | 200 | @Override 201 | public DeclarationFinder getDeclarationFinder() { 202 | return new TSDeclarationFinder(); 203 | } 204 | 205 | } 206 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/typinghooks/TSTypedBreakInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2013 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.typinghooks; 40 | 41 | import java.util.Arrays; 42 | import java.util.List; 43 | import javax.swing.text.BadLocationException; 44 | import net.dfranek.typoscript.TSLanguage; 45 | import net.dfranek.typoscript.lexer.TSLexerUtils; 46 | import net.dfranek.typoscript.lexer.TSTokenId; 47 | import org.netbeans.api.editor.mimelookup.MimePath; 48 | import org.netbeans.api.editor.mimelookup.MimeRegistration; 49 | import org.netbeans.api.lexer.Token; 50 | import org.netbeans.api.lexer.TokenId; 51 | import org.netbeans.api.lexer.TokenSequence; 52 | import org.netbeans.editor.BaseDocument; 53 | import org.netbeans.editor.Utilities; 54 | import org.netbeans.modules.csl.api.OffsetRange; 55 | import org.netbeans.modules.editor.indent.api.IndentUtils; 56 | import org.netbeans.spi.editor.typinghooks.TypedBreakInterceptor; 57 | 58 | /** 59 | * 60 | * @author Daniel Franek 61 | */ 62 | public class TSTypedBreakInterceptor implements TypedBreakInterceptor { 63 | 64 | @Override 65 | public boolean beforeInsert(Context cntxt) throws BadLocationException { 66 | return false; 67 | } 68 | 69 | @Override 70 | public void insert(MutableContext context) throws BadLocationException { 71 | final BaseDocument doc = (BaseDocument) context.getDocument(); 72 | int offset = context.getCaretOffset(); 73 | int lineBegin = Utilities.getRowStart(doc, offset); 74 | int lineEnd = Utilities.getRowEnd(doc, offset); 75 | if (lineBegin == offset && lineEnd == offset) { 76 | // Pressed return on a blank newline - do nothing 77 | return; 78 | } 79 | TokenSequence ts = TSLexerUtils.getTSTokenSequence(doc, offset); 80 | if (ts == null) { 81 | return; 82 | } 83 | ts.move(offset); 84 | if (!ts.moveNext() && !ts.movePrevious()) { 85 | return; 86 | } 87 | Token token = ts.token(); 88 | TokenId id = token.id(); 89 | 90 | // Insert an end statement? Insert a } marker? 91 | int[] startOfContext = new int[1]; 92 | TSTokenId completeIn = findContextForEnd(ts, offset, startOfContext); 93 | boolean insert = completeIn != null && isEndMissing(doc, offset, completeIn); 94 | if (insert) { 95 | int indent = IndentUtils.lineIndent(doc, IndentUtils.lineStartOffset(doc, startOfContext[0])); 96 | int afterLastNonWhite = Utilities.getRowLastNonWhite(doc, offset); 97 | 98 | int newIndent = ((indent / IndentUtils.tabSize(doc)) + 1) * IndentUtils.tabSize(doc); 99 | 100 | StringBuilder sb = new StringBuilder("\n"); 101 | String restOfLine = doc.getText(offset, Utilities.getRowEnd(doc, afterLastNonWhite) - offset); 102 | sb.append(restOfLine); 103 | sb.append(IndentUtils.createIndentString(doc, newIndent)); 104 | sb.append("\n"); //NOI18N 105 | sb.append(IndentUtils.createIndentString(doc, indent)); 106 | doc.remove(offset, restOfLine.length()); 107 | if(completeIn == TSTokenId.TS_CURLY_OPEN) { 108 | sb.append('}'); 109 | } 110 | if(completeIn == TSTokenId.TS_PARANTHESE_OPEN) { 111 | sb.append(')'); 112 | } 113 | 114 | context.setText(sb.toString(), 0, IndentUtils.createIndentString(doc, newIndent).length()+1); 115 | } 116 | } 117 | 118 | private TSTokenId findContextForEnd(TokenSequence ts, int offset, int[] startOfContext) { 119 | if (ts == null) { 120 | return null; 121 | } 122 | if (ts.offset() != offset) { 123 | ts.move(offset); 124 | 125 | if (!ts.moveNext() && !ts.movePrevious()) { 126 | return null; 127 | } 128 | } 129 | TSTokenId result = null; 130 | 131 | // at fist there should be find a bracket '{' or column ':' 132 | Token bracketColumnToken = TSLexerUtils.findPrevious(ts, 133 | Arrays.asList(TSTokenId.TS_COMMENT, TSTokenId.WHITESPACE, TSTokenId.TS_NL, TSTokenId.TS_VALUE, TSTokenId.TS_MULTILINE_VALUE) 134 | ); 135 | 136 | if (bracketColumnToken != null 137 | && (bracketColumnToken.id() == TSTokenId.TS_CURLY_OPEN || 138 | bracketColumnToken.id() == TSTokenId.TS_PARANTHESE_OPEN 139 | )) { 140 | startOfContext[0] = ts.offset(); 141 | // we are interested only in adding end for { or alternative syntax : 142 | List lookFor = Arrays.asList(TSTokenId.TS_CURLY_CLOSE, TSTokenId.TS_CURLY_OPEN, TSTokenId.TS_PARANTHESE_CLOSE, TSTokenId.TS_PARANTHESE_OPEN); 143 | Token keyToken = TSLexerUtils.findPreviousToken(ts, lookFor); 144 | 145 | if (bracketColumnToken.id() == TSTokenId.TS_CURLY_OPEN) { 146 | result = TSTokenId.TS_CURLY_OPEN; 147 | } 148 | 149 | if (bracketColumnToken.id() == TSTokenId.TS_PARANTHESE_OPEN) { 150 | result = TSTokenId.TS_PARANTHESE_OPEN; 151 | } 152 | 153 | if (keyToken.id() != TSTokenId.TS_CURLY_CLOSE && keyToken.id() != TSTokenId.TS_PARANTHESE_CLOSE) { 154 | startOfContext[0] = ts.offset(); 155 | } 156 | } 157 | ts.move(offset); 158 | if (!ts.moveNext() && !ts.movePrevious()) { 159 | return null; 160 | } 161 | return result; 162 | } 163 | 164 | private boolean isEndMissing(BaseDocument doc, int offset, TSTokenId startTokenId) throws BadLocationException { 165 | TokenSequence ts = TSLexerUtils.getTSTokenSequence(doc, offset); 166 | if (ts == null) { 167 | return false; 168 | } 169 | ts.move(0); 170 | if (!ts.moveNext() && !ts.movePrevious()) { 171 | return false; 172 | } 173 | Token token; 174 | int curlyBalance = 0; 175 | boolean curlyProcessed = false; 176 | if (startTokenId == TSTokenId.TS_CURLY_OPEN) { 177 | do { 178 | token = ts.token(); 179 | if (token.id() == TSTokenId.TS_CURLY_CLOSE) { 180 | curlyBalance--; 181 | curlyProcessed = true; 182 | } else if (token.id() == TSTokenId.TS_CURLY_OPEN) { //NOI18N 183 | curlyBalance++; 184 | curlyProcessed = true; 185 | } 186 | 187 | if (curlyBalance == 0 && curlyProcessed && ts.offset() > offset) { 188 | break; 189 | } 190 | } while (ts.moveNext()); 191 | return curlyBalance > 0; 192 | } 193 | 194 | ts.move(offset); 195 | if (startTokenId == TSTokenId.TS_PARANTHESE_OPEN) { 196 | OffsetRange r = TSLexerUtils.findFwd(ts, TSTokenId.TS_PARANTHESE_OPEN, '(', TSTokenId.TS_PARANTHESE_CLOSE, ')'); 197 | if (r == OffsetRange.NONE) { 198 | return true; 199 | } 200 | } 201 | 202 | return false; 203 | } 204 | 205 | @Override 206 | public void afterInsert(Context cntxt) throws BadLocationException { 207 | // deliberatly empty 208 | } 209 | 210 | @Override 211 | public void cancelled(Context cntxt) { 212 | // deliberatly empty 213 | } 214 | 215 | @MimeRegistration(mimeType = TSLanguage.TS_MIME_TYPE, service = TypedBreakInterceptor.Factory.class) 216 | public static class PhpFactory implements TypedBreakInterceptor.Factory { 217 | 218 | @Override 219 | public TypedBreakInterceptor createTypedBreakInterceptor(MimePath mimePath) { 220 | return new TSTypedBreakInterceptor(); 221 | } 222 | } 223 | 224 | } 225 | -------------------------------------------------------------------------------- /test/unit/src/net/dfranek/typoscript/lexer/TSScannerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.lexer; 40 | 41 | import junit.framework.TestCase; 42 | import org.junit.Test; 43 | import org.netbeans.api.lexer.TokenSequence; 44 | import org.openide.util.Utilities; 45 | 46 | /** 47 | * 48 | * @author Daniel Franek 49 | */ 50 | public class TSScannerTest extends TestCase { 51 | 52 | @Test 53 | public void testLineComment() { 54 | TokenSequence ts = TSLexerTestUtils.seqForText("# comment\n", TSTokenId.getLanguage()); 55 | TSLexerTestUtils.next(ts, TSTokenId.TS_COMMENT, "# comment"); 56 | TSLexerTestUtils.next(ts, TSTokenId.TS_NL, "\n"); 57 | } 58 | 59 | @Test 60 | public void testMultiLineComment() { 61 | TokenSequence ts = TSLexerTestUtils.seqForText("/* first line\n*second line\n*/\n", TSTokenId.getLanguage()); 62 | TSLexerTestUtils.next(ts, TSTokenId.TS_MULTILINE_COMMENT, "/* first line\n"); 63 | TSLexerTestUtils.next(ts, TSTokenId.TS_MULTILINE_COMMENT, "*second line\n"); 64 | TSLexerTestUtils.next(ts, TSTokenId.TS_MULTILINE_COMMENT, "*/"); 65 | TSLexerTestUtils.next(ts, TSTokenId.TS_NL, "\n"); 66 | } 67 | 68 | @Test 69 | public void testProperty() { 70 | TokenSequence ts = TSLexerTestUtils.seqForText("page.10.marks.TEST = something", TSTokenId.getLanguage()); 71 | TSLexerTestUtils.next(ts, TSTokenId.TS_KEYWORD, "page"); 72 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, "."); 73 | TSLexerTestUtils.next(ts, TSTokenId.TS_NUMBER, "10"); 74 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, "."); 75 | TSLexerTestUtils.next(ts, TSTokenId.TS_KEYWORD, "marks"); 76 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, "."); 77 | TSLexerTestUtils.next(ts, TSTokenId.TS_PROPERTY, "TEST"); 78 | TSLexerTestUtils.next(ts, TSTokenId.WHITESPACE, " "); 79 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, "="); 80 | TSLexerTestUtils.next(ts, TSTokenId.WHITESPACE, " "); 81 | TSLexerTestUtils.next(ts, TSTokenId.TS_VALUE, "something"); 82 | } 83 | 84 | @Test 85 | public void testExampleFile() throws Exception { 86 | TokenSequence ts = TSLexerTestUtils.seqForText(TSLexerTestUtils.getFileContent(Utilities.toFile(TSScannerTest.class.getResource("/net/dfranek/typoscript/lexer/TSExample").toURI())), TSTokenId.getLanguage()); 87 | TSLexerTestUtils.next(ts, TSTokenId.TS_PROPERTY, "headerimg"); 88 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, "."); 89 | TSLexerTestUtils.next(ts, TSTokenId.TS_RESERVED, "file"); 90 | TSLexerTestUtils.next(ts, TSTokenId.WHITESPACE, " "); 91 | TSLexerTestUtils.next(ts, TSTokenId.TS_CURLY_OPEN, "{"); 92 | TSLexerTestUtils.next(ts, TSTokenId.TS_NL, "\n"); 93 | TSLexerTestUtils.next(ts, TSTokenId.WHITESPACE, "\t"); 94 | TSLexerTestUtils.next(ts, TSTokenId.TS_KEYWORD, "XY"); 95 | TSLexerTestUtils.next(ts, TSTokenId.WHITESPACE, " "); 96 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, "="); 97 | TSLexerTestUtils.next(ts, TSTokenId.WHITESPACE, " "); 98 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, "["); 99 | TSLexerTestUtils.next(ts, TSTokenId.TS_NUMBER, "10"); 100 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, "."); 101 | TSLexerTestUtils.next(ts, TSTokenId.TS_VALUE, "w"); 102 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, "]"); 103 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, "+"); 104 | TSLexerTestUtils.next(ts, TSTokenId.TS_NUMBER, "2"); 105 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, ","); 106 | TSLexerTestUtils.next(ts, TSTokenId.TS_NUMBER, "20"); 107 | TSLexerTestUtils.next(ts, TSTokenId.TS_NL, "\n"); 108 | TSLexerTestUtils.next(ts, TSTokenId.TS_CURLY_CLOSE, "}"); 109 | TSLexerTestUtils.next(ts, TSTokenId.TS_NL, "\n"); 110 | TSLexerTestUtils.next(ts, TSTokenId.TS_NL, "\n"); 111 | TSLexerTestUtils.next(ts, TSTokenId.TS_CONDITION, "[globalVar=TSFE:type = 0]"); 112 | TSLexerTestUtils.next(ts, TSTokenId.TS_NL, "\n"); 113 | TSLexerTestUtils.next(ts, TSTokenId.WHITESPACE, "\t"); 114 | TSLexerTestUtils.next(ts, TSTokenId.TS_KEYWORD, "page"); 115 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, "."); 116 | TSLexerTestUtils.next(ts, TSTokenId.TS_RESERVED, "typeNum"); 117 | TSLexerTestUtils.next(ts, TSTokenId.WHITESPACE, " "); 118 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, "="); 119 | TSLexerTestUtils.next(ts, TSTokenId.WHITESPACE, " "); 120 | TSLexerTestUtils.next(ts, TSTokenId.TS_NUMBER, "0"); 121 | TSLexerTestUtils.next(ts, TSTokenId.TS_NL, "\n"); 122 | TSLexerTestUtils.next(ts, TSTokenId.TS_CONDITION, "[global]"); 123 | TSLexerTestUtils.next(ts, TSTokenId.TS_NL, "\n"); 124 | TSLexerTestUtils.next(ts, TSTokenId.TS_NL, "\n"); 125 | TSLexerTestUtils.next(ts, TSTokenId.TS_KEYWORD, "page"); 126 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, "."); 127 | TSLexerTestUtils.next(ts, TSTokenId.TS_NUMBER, "10"); 128 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, "."); 129 | TSLexerTestUtils.next(ts, TSTokenId.TS_RESERVED, "value"); 130 | TSLexerTestUtils.next(ts, TSTokenId.WHITESPACE, " "); 131 | TSLexerTestUtils.next(ts, TSTokenId.TS_PARANTHESE_OPEN, "("); 132 | TSLexerTestUtils.next(ts, TSTokenId.TS_MULTILINE_VALUE, "\n\tMulti\n\tLine\n\tValue\n"); 133 | TSLexerTestUtils.next(ts, TSTokenId.TS_PARANTHESE_CLOSE, ")"); 134 | } 135 | 136 | @Test 137 | public void testEqualsInValue() { 138 | TokenSequence ts = TSLexerTestUtils.seqForText("page.10.marks.TEST.select.where = colPos=0\npage.typeNum=0", TSTokenId.getLanguage()); 139 | TSLexerTestUtils.next(ts, TSTokenId.TS_KEYWORD, "page"); 140 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, "."); 141 | TSLexerTestUtils.next(ts, TSTokenId.TS_NUMBER, "10"); 142 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, "."); 143 | TSLexerTestUtils.next(ts, TSTokenId.TS_KEYWORD, "marks"); 144 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, "."); 145 | TSLexerTestUtils.next(ts, TSTokenId.TS_PROPERTY, "TEST"); 146 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, "."); 147 | TSLexerTestUtils.next(ts, TSTokenId.TS_FUNCTION, "select"); 148 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, "."); 149 | TSLexerTestUtils.next(ts, TSTokenId.TS_RESERVED, "where"); 150 | TSLexerTestUtils.next(ts, TSTokenId.WHITESPACE, " "); 151 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, "="); 152 | TSLexerTestUtils.next(ts, TSTokenId.WHITESPACE, " "); 153 | TSLexerTestUtils.next(ts, TSTokenId.TS_VALUE, "colPos"); 154 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, "="); 155 | TSLexerTestUtils.next(ts, TSTokenId.TS_NUMBER, "0"); 156 | TSLexerTestUtils.next(ts, TSTokenId.TS_NL, "\n"); 157 | TSLexerTestUtils.next(ts, TSTokenId.TS_KEYWORD, "page"); 158 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, "."); 159 | TSLexerTestUtils.next(ts, TSTokenId.TS_RESERVED, "typeNum"); 160 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, "="); 161 | TSLexerTestUtils.next(ts, TSTokenId.TS_NUMBER, "0"); 162 | } 163 | 164 | public void testOpeningCurly() { 165 | TokenSequence ts = TSLexerTestUtils.seqForText("page{", TSTokenId.getLanguage()); 166 | TSLexerTestUtils.next(ts, TSTokenId.TS_KEYWORD, "page"); 167 | TSLexerTestUtils.next(ts, TSTokenId.TS_CURLY_OPEN, "{"); 168 | } 169 | 170 | public void testConstantAndComment() { 171 | TokenSequence ts = TSLexerTestUtils.seqForText("shortcutIcon = {$filepaths.templates.images}favicon.icon # But doesn't work ofcourse", TSTokenId.getLanguage()); 172 | TSLexerTestUtils.next(ts, TSTokenId.TS_RESERVED, "shortcutIcon"); 173 | TSLexerTestUtils.next(ts, TSTokenId.WHITESPACE, " "); 174 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, "="); 175 | TSLexerTestUtils.next(ts, TSTokenId.WHITESPACE, " "); 176 | TSLexerTestUtils.next(ts, TSTokenId.TS_CONSTANT, "{$filepaths.templates.images}"); 177 | TSLexerTestUtils.next(ts, TSTokenId.TS_VALUE, "favicon"); 178 | TSLexerTestUtils.next(ts, TSTokenId.TS_OPERATOR, "."); 179 | TSLexerTestUtils.next(ts, TSTokenId.TS_RESERVED, "icon"); 180 | } 181 | 182 | } 183 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/lexer/TSLexerUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.lexer; 40 | 41 | import com.google.gson.Gson; 42 | import java.io.InputStreamReader; 43 | import java.util.ArrayList; 44 | import java.util.Collection; 45 | import java.util.HashMap; 46 | import java.util.List; 47 | import java.util.Map; 48 | import javax.swing.text.Document; 49 | import org.netbeans.api.lexer.Token; 50 | import org.netbeans.api.lexer.TokenHierarchy; 51 | import org.netbeans.api.lexer.TokenId; 52 | import org.netbeans.api.lexer.TokenSequence; 53 | import org.netbeans.modules.csl.api.OffsetRange; 54 | 55 | /** 56 | * 57 | * @author Daniel Franek 58 | */ 59 | public class TSLexerUtils { 60 | 61 | protected static HashMap> completionList = new HashMap<>(); 62 | protected static HashMap keywords; 63 | 64 | 65 | @SuppressWarnings("unchecked") 66 | public static TokenSequence getTSTokenSequence(TokenHierarchy th, int offset) { 67 | TokenSequence ts = th == null ? null : th.tokenSequence(TSTokenId.getLanguage()); 68 | if (ts == null) { 69 | // Possibly an embedding scenario such as an RHTML file 70 | // First try with backward bias true 71 | List> list = th.embeddedTokenSequences(offset, true); 72 | for (TokenSequence t : list) { 73 | if (t.language() == TSTokenId.getLanguage()) { 74 | ts = (TokenSequence) t; 75 | break; 76 | } 77 | } 78 | if (ts == null) { 79 | list = th.embeddedTokenSequences(offset, false); 80 | for (TokenSequence t : list) { 81 | if (t.language() == TSTokenId.getLanguage()) { 82 | ts = (TokenSequence) t; 83 | break; 84 | } 85 | } 86 | } 87 | } 88 | return ts; 89 | } 90 | 91 | @SuppressWarnings("unchecked") 92 | public static TokenSequence getTSTokenSequence(Document doc, int offset) { 93 | TokenHierarchy th = TokenHierarchy.get(doc); 94 | return getTSTokenSequence(th, offset); 95 | } 96 | 97 | public static boolean textEquals(CharSequence text1, char... text2) { 98 | int len = text1.length(); 99 | if (len == text2.length) { 100 | for (int i = len - 1; i >= 0; i--) { 101 | if (text1.charAt(i) != text2[i]) { 102 | return false; 103 | } 104 | } 105 | return true; 106 | } 107 | return false; 108 | } 109 | 110 | /** 111 | * Search forwards in the token sequence until a token of type 112 | * down is found 113 | */ 114 | public static OffsetRange findFwd(TokenSequence ts, TSTokenId tokenUpId, char up, TSTokenId tokenDownId, char down) { 115 | int balance = 0; 116 | 117 | while (ts.moveNext()) { 118 | Token token = ts.token(); 119 | 120 | if ((token.id() == tokenUpId && textEquals(token.text(), up))/* 121 | * || (tokenUpId == TSTokenId.TS_CURLY_OPEN && token.id() == 122 | * TSTokenId.PHP_TOKEN && 123 | * token.text().charAt(token.text().length() - 1) == '{') 124 | */) { 125 | balance++; 126 | } else if (token.id() == tokenDownId && textEquals(token.text(), down)) { 127 | if (balance == 0) { 128 | return new OffsetRange(ts.offset(), ts.offset() + token.length()); 129 | } 130 | 131 | balance--; 132 | } 133 | } 134 | 135 | return OffsetRange.NONE; 136 | } 137 | 138 | /** 139 | * Search backwards in the token sequence until a token of type 140 | * up is found 141 | */ 142 | public static OffsetRange findBwd(TokenSequence ts, TSTokenId tokenUpId, char up, TSTokenId tokenDownId, char down) { 143 | int balance = 0; 144 | 145 | while (ts.movePrevious()) { 146 | Token token = ts.token(); 147 | TokenId id = token.id(); 148 | 149 | if (token.id() == tokenUpId && textEquals(token.text(), up)/* 150 | * || (tokenUpId == PHPTokenId.PHP_CURLY_OPEN && token.id() 151 | * == PHPTokenId.PHP_TOKEN && 152 | * token.text().charAt(token.text().length() - 1) == '{') 153 | */) { 154 | if (balance == 0) { 155 | return new OffsetRange(ts.offset(), ts.offset() + token.length()); 156 | } 157 | 158 | balance++; 159 | } else if (token.id() == tokenDownId && textEquals(token.text(), down)) { 160 | balance--; 161 | } 162 | } 163 | 164 | return OffsetRange.NONE; 165 | } 166 | 167 | public static OffsetRange findNextStartsWith(TokenSequence ts, TSTokenId tokenId, String startsWith) { 168 | while (ts.moveNext()) { 169 | Token token = ts.token(); 170 | TokenId id = token.id(); 171 | if (token.id() == tokenId && token.text().toString().startsWith(startsWith)) { 172 | return new OffsetRange(ts.offset(), ts.offset() + token.length()); 173 | } 174 | } 175 | return OffsetRange.NONE; 176 | } 177 | 178 | 179 | public static OffsetRange findNextEndsWith(TokenSequence ts, TSTokenId tokenId, String endsWith) { 180 | while (ts.moveNext()) { 181 | Token token = ts.token(); 182 | TokenId id = token.id(); 183 | if (token.id() == tokenId && token.text().toString().endsWith(endsWith)) { 184 | return new OffsetRange(ts.offset(), ts.offset() + token.length()); 185 | } 186 | } 187 | return OffsetRange.NONE; 188 | } 189 | 190 | 191 | public static Token findFwdNonSpace(TokenSequence ts) { 192 | while (ts.moveNext() && ts.token().id().equals(TSTokenId.WHITESPACE)) {} 193 | return ts.token(); 194 | } 195 | 196 | public static Token findBwdNonSpace(TokenSequence ts) { 197 | while (ts.movePrevious() && ts.token().id().equals(TSTokenId.WHITESPACE)) {} 198 | return ts.token(); 199 | } 200 | 201 | public static String getWordFromXML(String word) { 202 | String propertyType = ""; 203 | if(keywords.containsKey(word)) { 204 | propertyType = keywords.get(word); 205 | } 206 | 207 | return propertyType; 208 | } 209 | 210 | public static Collection getAllKeywordsOfType(String type) { 211 | if(completionList.containsKey(type)) { 212 | return completionList.get(type); 213 | } 214 | Collection properties = new ArrayList<>(); 215 | for (Map.Entry entry : keywords.entrySet()) { 216 | String property = entry.getKey(); 217 | if (entry.getValue().equals(type)) { 218 | properties.add(property); 219 | } 220 | } 221 | completionList.put(type, properties); 222 | 223 | return properties; 224 | } 225 | 226 | @SuppressWarnings("unchecked") 227 | static void initKeywords() { 228 | Gson gson = new Gson(); 229 | keywords = gson.fromJson(new InputStreamReader(TSLexerUtils.class.getResourceAsStream("/net/dfranek/typoscript/resources/properties.json")), HashMap.class); 230 | } 231 | 232 | public static boolean tokenIsKeyword(TSTokenId id) { 233 | return id.equals(TSTokenId.TS_OBJECT) || id.equals(TSTokenId.TS_EXTENSION) || id.equals(TSTokenId.TS_PROPERTY) || id.equals(TSTokenId.TS_NUMBER) || id.equals(TSTokenId.TS_KEYWORD) || id.equals(TSTokenId.TS_RESERVED) || id.equals(TSTokenId.TS_FUNCTION); 234 | } 235 | 236 | public static Token findPrevious(TokenSequence ts, List ignores) { 237 | if (ignores.contains(ts.token().id())) { 238 | while (ts.movePrevious() && ignores.contains(ts.token().id())) { 239 | } 240 | } 241 | return ts.token(); 242 | } 243 | 244 | public static Token findPreviousToken(TokenSequence ts, List lookfor) { 245 | if (!lookfor.contains(ts.token().id())) { 246 | while (ts.movePrevious() && !lookfor.contains(ts.token().id())) { 247 | } 248 | } 249 | return ts.token(); 250 | } 251 | 252 | } 253 | -------------------------------------------------------------------------------- /src/net/dfranek/typoscript/parser/TSTokenParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright 2011 Daniel Franek. 5 | * 6 | * Oracle and Java are registered trademarks of Oracle and/or its affiliates. 7 | * Other names may be trademarks of their respective owners. 8 | * 9 | * The contents of this file are subject to the terms of either the GNU 10 | * General Public License Version 2 only ("GPL") or the Common 11 | * Development and Distribution License("CDDL") (collectively, the 12 | * "License"). You may not use this file except in compliance with the 13 | * License. You can obtain a copy of the License at 14 | * http://www.netbeans.org/cddl-gplv2.html 15 | * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the 16 | * specific language governing permissions and limitations under the 17 | * License. When distributing the software, include this License Header 18 | * Notice in each file and include the License file at 19 | * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this 20 | * particular file as subject to the "Classpath" exception as provided 21 | * by Oracle in the GPL Version 2 section of the License file that 22 | * accompanied this code. If applicable, add the following below the 23 | * License Header, with the fields enclosed by brackets [] replaced by 24 | * your own identifying information: 25 | * "Portions Copyrighted [year] [name of copyright owner]" 26 | * 27 | * If you wish your version of this file to be governed by only the CDDL 28 | * or only the GPL Version 2, indicate your decision by adding 29 | * "[Contributor] elects to include this software in this distribution 30 | * under the [CDDL or GPL Version 2] license." If you do not indicate a 31 | * single choice of license, a recipient has the option to distribute 32 | * your version of this file under either the CDDL, the GPL Version 2 or 33 | * to extend the choice of license to its licensees as provided above. 34 | * However, if you add GPL Version 2 code and therefore, elected the GPL 35 | * Version 2 license, then the option applies only if the new code is 36 | * made subject to such option by the copyright holder. 37 | * 38 | */ 39 | package net.dfranek.typoscript.parser; 40 | 41 | import java.util.Arrays; 42 | import java.util.HashMap; 43 | import java.util.List; 44 | import java.util.Map; 45 | import net.dfranek.typoscript.lexer.TSLexerUtils; 46 | import net.dfranek.typoscript.lexer.TSTokenId; 47 | import net.dfranek.typoscript.parser.ast.TSASTNode; 48 | import net.dfranek.typoscript.parser.ast.TSASTNodeType; 49 | import org.netbeans.api.lexer.Token; 50 | import org.netbeans.api.lexer.TokenSequence; 51 | import org.netbeans.modules.csl.api.OffsetRange; 52 | import org.netbeans.modules.csl.api.Severity; 53 | import org.netbeans.modules.parsing.api.Snapshot; 54 | 55 | /** 56 | * 57 | * @author Daniel Franek, Eric Waldburger 58 | */ 59 | public class TSTokenParser { 60 | 61 | private final TokenSequence sequence; 62 | private Snapshot snapshot; 63 | private TSBracketNode last = new TSBracketNode("root", null); 64 | private final TSBracketNode root = last; 65 | private final TSASTNode tree; 66 | private boolean conditionOpen; 67 | private final TSParserResult result; 68 | 69 | TSTokenParser(TokenSequence source, Snapshot snapshot) { 70 | this.conditionOpen = false; 71 | sequence = source; 72 | this.snapshot = snapshot; 73 | result = new TSParserResult(snapshot); 74 | tree = new TSASTNode("", "", TSASTNodeType.ROOTLEVEL, 0, 1); 75 | } 76 | 77 | TSTokenParser(TokenSequence source) { 78 | this.conditionOpen = false; 79 | sequence = source; 80 | result = new TSParserResult(snapshot); 81 | tree = new TSASTNode("", "", TSASTNodeType.ROOTLEVEL, 0, 1); 82 | } 83 | 84 | public TSParserResult analyze() { 85 | result.setSequence(sequence); 86 | 87 | checkErrors(); 88 | buildTree(); 89 | 90 | return result; 91 | } 92 | 93 | private void checkBraces(TSTokenId id, Token t, TokenSequence ts) { 94 | List tokensToCheck = Arrays.asList( 95 | TSTokenId.TS_CURLY_OPEN, 96 | TSTokenId.TS_CURLY_CLOSE, 97 | TSTokenId.TS_PARANTHESE_OPEN, 98 | TSTokenId.TS_PARANTHESE_CLOSE, 99 | TSTokenId.TS_CONDITION, 100 | TSTokenId.TS_VALUE, 101 | TSTokenId.TS_MULTILINE_VALUE, 102 | TSTokenId.TS_OPERATOR 103 | ); 104 | 105 | //Bracket Handling 106 | if(tokensToCheck.contains(id)) { 107 | String tokenText = t.text().toString(); 108 | if (id == TSTokenId.TS_CURLY_OPEN) { 109 | if (last == null) { 110 | last = new TSBracketNode("{", null, ts.offset()); 111 | } else { 112 | last.setNext(new TSBracketNode("{", last, ts.offset())); 113 | last = last.getNext(); 114 | } 115 | result.addCodeBlock(new OffsetRange(last.getOffset(), ts.offset())); 116 | } else if (id == TSTokenId.TS_CURLY_CLOSE) { 117 | if (last.getValue().equals("{")) { 118 | last = last.getPrev(); 119 | last.setNext(null); 120 | } else { 121 | result.addError(new TSError("No matching brace found for " + last.getValue(), snapshot.getSource().getFileObject(), id.getStart(), id.getEnd(), Severity.ERROR, new Object[]{this})); 122 | } 123 | } else if (id == TSTokenId.TS_PARANTHESE_OPEN) { 124 | if (last == null) { 125 | last = new TSBracketNode("(", null, ts.offset()); 126 | } else { 127 | last.setNext(new TSBracketNode("(", last, ts.offset())); 128 | last = last.getNext(); 129 | } 130 | result.addCodeBlock(new OffsetRange(last.getOffset(), ts.offset())); 131 | } else if (id == TSTokenId.TS_PARANTHESE_CLOSE) { 132 | if (last.getValue().equals("(")) { 133 | last = last.getPrev(); 134 | last.setNext(null); 135 | } else { 136 | result.addError(new TSError("No matching paranthese found for " + last.getValue(), snapshot.getSource().getFileObject(), id.getStart(), id.getEnd(), Severity.ERROR, new Object[]{this})); 137 | } 138 | } else if (tokenText.equals("[")) { 139 | if (last == null) { 140 | last = new TSBracketNode("[", null, ts.offset()); 141 | } else { 142 | last.setNext(new TSBracketNode("[", last, ts.offset())); 143 | last = last.getNext(); 144 | } 145 | } else if (tokenText.equals("]")) { 146 | if (last.getValue().equals("[")) { 147 | last = last.getPrev(); 148 | last.setNext(null); 149 | } else { 150 | result.addError(new TSError("No matching bracket found for " + last.getValue(), snapshot.getSource().getFileObject(), id.getStart(), id.getEnd(), Severity.ERROR, new Object[]{this})); 151 | } 152 | } else if (id == TSTokenId.TS_CONDITION && (!tokenText.equals("[global]") && !tokenText.equals("[end]"))) { 153 | conditionOpen = true; 154 | result.addCodeBlock(new OffsetRange(ts.offset(), ts.offset() + t.length())); 155 | } else if (id == TSTokenId.TS_CONDITION && tokenText.equals("[global]")) { 156 | conditionOpen = false; 157 | } 158 | } 159 | } 160 | 161 | public TSASTNode buildTree() { 162 | TSASTNode node; 163 | Token t; 164 | TSTokenId id; 165 | TSASTNode actNode = tree; 166 | 167 | sequence.moveStart(); 168 | int curlyDepth = 0; 169 | Map curlyHierarchy = new HashMap<>(); 170 | curlyHierarchy.put(curlyDepth, tree); 171 | while (sequence.moveNext()) { 172 | //content of token 173 | t = sequence.token(); 174 | //type of token 175 | id = t.id(); 176 | if (isPossibleParent(id)) { 177 | TSASTNode newActNode = actNode; 178 | node = new TSASTNode(t.text().toString(), "", TSASTNodeType.getNodeTypeForObject(t.text().toString()), sequence.offset(), t.length()); 179 | if (actNode.hasChild(node)) { 180 | node = actNode.getChild(node.getName()); 181 | } 182 | 183 | Token tVal = TSLexerUtils.findFwdNonSpace(sequence); 184 | if (tVal.id().equals(TSTokenId.TS_OPERATOR) && tVal.text().toString().equals("=")) { 185 | tVal = TSLexerUtils.findFwdNonSpace(sequence); 186 | if (tVal.id().equals(TSTokenId.TS_OBJECT)) { 187 | node.setType(TSASTNodeType.getNodeTypeForObject(tVal.text().toString(), actNode)); 188 | } else { 189 | String tokenText = ""; 190 | sequence.movePrevious(); 191 | while (sequence.moveNext() && !sequence.token().id().equals(TSTokenId.TS_NL)) { 192 | tokenText += sequence.token().text().toString(); 193 | } 194 | sequence.movePrevious(); 195 | node.setValue(tokenText); 196 | if(!node.isTypeSet()) { 197 | node.setType(TSASTNodeType.VALUE); 198 | } 199 | } 200 | newActNode = actNode; 201 | } else if (tVal.id().equals(TSTokenId.TS_PARANTHESE_OPEN)||tVal.id().equals(TSTokenId.TS_PARANTHESE_CLOSE)) { 202 | tVal = TSLexerUtils.findFwdNonSpace(sequence); 203 | node.setValue(tVal.text().toString().trim()); 204 | node.setType(TSASTNodeType.VALUE); 205 | } else if ((tVal.id().equals(TSTokenId.TS_OPERATOR) && tVal.text().toString().equals("."))) { 206 | newActNode = node; 207 | } else if ((tVal.id().equals(TSTokenId.TS_OPERATOR) && tVal.text().toString().equals(">"))) { 208 | node.setType(TSASTNodeType.CLEARED_PROPERY); 209 | } else if ((tVal.id().equals(TSTokenId.TS_OPERATOR) && tVal.text().toString().equals("<"))) { 210 | String tokenText = ""; 211 | while (sequence.moveNext() && !sequence.token().id().equals(TSTokenId.TS_NL)) { 212 | tokenText += sequence.token().text().toString(); 213 | } 214 | sequence.movePrevious(); 215 | node.setValue(tokenText.trim()); 216 | node.setType(TSASTNodeType.COPIED_PROPERTY); 217 | } else if (tVal.id().equals(TSTokenId.TS_CURLY_OPEN)) { 218 | newActNode = node; 219 | curlyDepth++; 220 | curlyHierarchy.put(curlyDepth, node); 221 | } 222 | if (!actNode.hasChild(node)) { 223 | actNode.addChild(node); 224 | actNode = newActNode; 225 | } else { 226 | actNode = newActNode; 227 | } 228 | } 229 | if (id.equals(TSTokenId.TS_NL)) { 230 | actNode = curlyHierarchy.get(curlyDepth); 231 | } 232 | if (curlyDepth > 0 && id.equals(TSTokenId.TS_CURLY_CLOSE)) { 233 | curlyDepth--; 234 | actNode = curlyHierarchy.get(curlyDepth); 235 | } else if(id.equals(TSTokenId.TS_CONDITION)) { 236 | if (t.text().toString().equals("[global]")) { 237 | actNode = tree; 238 | curlyHierarchy.put(curlyDepth, tree); 239 | } else { 240 | node = new TSASTNode(t.text().toString(), "", TSASTNodeType.CONDITION, sequence.offset(), t.length(), String.valueOf(sequence.offset())); 241 | tree.addChild(node); 242 | curlyHierarchy.put(0, node); 243 | } 244 | } 245 | } 246 | 247 | result.setTree(tree); 248 | return tree; 249 | } 250 | 251 | public void checkErrors() { 252 | Token t; 253 | TSTokenId id; 254 | 255 | while (sequence.moveNext()) { 256 | //content of token 257 | t = sequence.token(); 258 | //type of token 259 | id = t.id(); 260 | 261 | if (id == TSTokenId.TS_MULTILINE_COMMENT && t.text().toString().startsWith("/*")) { 262 | result.addCodeBlock(new OffsetRange(sequence.offset(), sequence.offset() + 1)); 263 | } 264 | 265 | // DF: ausgelagert in eigene Funktion 266 | checkBraces(id, t, sequence); 267 | } 268 | 269 | if (conditionOpen) { 270 | result.addError(new TSError("Not all conditions were ended with [global]", snapshot.getSource().getFileObject(), snapshot.getSource().getDocument(true).getLength() - 1, snapshot.getSource().getDocument(true).getLength(), Severity.WARNING, new Object[]{this})); 271 | } 272 | 273 | TSBracketNode end = root.getNext(); 274 | if (end != null) { 275 | String message; 276 | if ("(".equals(end.getValue())) { 277 | message = "A multiline value section is not ended with a parenthesis!"; 278 | } else { 279 | message = "An end brace is in excess."; 280 | } 281 | result.addError(new TSError(message, snapshot.getSource().getFileObject(), snapshot.getSource().getDocument(true).getLength() - 1, snapshot.getSource().getDocument(true).getLength(), Severity.ERROR, new Object[]{this})); 282 | } 283 | 284 | } 285 | 286 | protected boolean isPossibleParent(TSTokenId id) { 287 | return TSLexerUtils.tokenIsKeyword(id); 288 | } 289 | 290 | } 291 | -------------------------------------------------------------------------------- /nbproject/project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | org.netbeans.modules.apisupport.project 4 | 5 | 6 | net.dfranek.typoscript 7 | 8 | 9 | 10 | org.netbeans.api.templates 11 | 12 | 13 | 14 | 1.5.1 15 | 16 | 17 | 18 | org.netbeans.core.multiview 19 | 20 | 21 | 22 | 1 23 | 1.29.1 24 | 25 | 26 | 27 | org.netbeans.modules.autoupdate.services 28 | 29 | 30 | 31 | 1.33.1 32 | 33 | 34 | 35 | org.netbeans.modules.csl.api 36 | 37 | 38 | 39 | 2 40 | 2.28.1.2.1.1.6 41 | 42 | 43 | 44 | org.netbeans.modules.editor.bracesmatching 45 | 46 | 47 | 48 | 0-1 49 | 1.22.1 50 | 51 | 52 | 53 | org.netbeans.modules.editor.fold 54 | 55 | 56 | 57 | 1 58 | 1.29.1.31 59 | 60 | 61 | 62 | org.netbeans.modules.editor.indent 63 | 64 | 65 | 66 | 2 67 | 1.34.1 68 | 69 | 70 | 71 | org.netbeans.modules.editor.lib 72 | 73 | 74 | 75 | 3 76 | 3.24.1.19.31 77 | 78 | 79 | 80 | org.netbeans.modules.editor.lib2 81 | 82 | 83 | 84 | 1 85 | 1.81.1.43 86 | 87 | 88 | 89 | org.netbeans.modules.editor.mimelookup 90 | 91 | 92 | 93 | 1 94 | 1.26.1 95 | 96 | 97 | 98 | org.netbeans.modules.lexer 99 | 100 | 101 | 102 | 2 103 | 1.46.1.1 104 | 105 | 106 | 107 | org.netbeans.modules.parsing.api 108 | 109 | 110 | 111 | 1 112 | 1.55.1.6 113 | 114 | 115 | 116 | org.netbeans.modules.parsing.indexing 117 | 118 | 119 | 120 | 9.6.1.1.1.8 121 | 122 | 123 | 124 | org.netbeans.spi.navigator 125 | 126 | 127 | 128 | 1 129 | 1.23.1 130 | 131 | 132 | 133 | org.openide.awt 134 | 135 | 136 | 137 | 7.62.1 138 | 139 | 140 | 141 | org.openide.dialogs 142 | 143 | 144 | 145 | 7.38.1 146 | 147 | 148 | 149 | org.openide.filesystems 150 | 151 | 152 | 153 | 7.62.1 154 | 155 | 156 | 157 | org.openide.loaders 158 | 159 | 160 | 161 | 7.57.1 162 | 163 | 164 | 165 | org.openide.modules 166 | 167 | 168 | 169 | 7.32.1 170 | 171 | 172 | 173 | org.openide.nodes 174 | 175 | 176 | 177 | 7.28.1 178 | 179 | 180 | 181 | org.openide.util 182 | 183 | 184 | 185 | 8.25.1 186 | 187 | 188 | 189 | org.openide.util.lookup 190 | 191 | 192 | 193 | 8.15.1 194 | 195 | 196 | 197 | org.openide.util.ui 198 | 199 | 200 | 201 | 9.3.1 202 | 203 | 204 | 205 | org.openide.windows 206 | 207 | 208 | 209 | 6.55.1 210 | 211 | 212 | 213 | 214 | 215 | unit 216 | 217 | org.netbeans.libs.junit4 218 | 219 | 220 | 221 | org.netbeans.modules.csl.api 222 | 223 | 224 | 225 | org.netbeans.modules.nbjunit 226 | 227 | 228 | 229 | 230 | 231 | 232 | ext/gson-2.2.2.jar 233 | release/modules/ext/gson-2.2.2.jar 234 | 235 | 236 | 237 | 238 | --------------------------------------------------------------------------------