/* * Copyright (c) Joachim Ansorg, [email protected] * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ansorgit.plugins.bash.lang.parser.eval; import com.ansorgit.plugins.bash.file.BashFileType; import com.ansorgit.plugins.bash.settings.BashProjectSettings; import com.intellij.lang.ASTNode; import com.intellij.lang.LanguageParserDefinitions; import com.intellij.lang.ParserDefinition; import com.intellij.lang.PsiBuilder; import com.intellij.lexer.Lexer; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.TokenType; import com.intellij.psi.tree.ILazyParseableElementType; import org.jetbrains.annotations.NotNull; public class BashEvalElementType extends ILazyParseableElementType { public BashEvalElementType() { super("eval block", BashFileType.BASH_LANGUAGE); } @Override protected ASTNode doParseContents(@NotNull ASTNode chameleon, @NotNull PsiElement psi) { Project project = psi.getProject(); boolean supportEvalEscapes = BashProjectSettings.storedSettings(project).isEvalEscapesEnabled(); String originalText = chameleon.getChars().toString(); ParserDefinition def = LanguageParserDefinitions.INSTANCE.forLanguage(BashFileType.BASH_LANGUAGE); boolean isDoubleQuoted = originalText.startsWith("\"") && originalText.endsWith("\""); boolean isSingleQuoted = originalText.startsWith("'") && originalText.endsWith("'"); boolean isEscapingSingleQuoted = originalText.startsWith("$'") && originalText.endsWith("'"); boolean isUnquoted = !isDoubleQuoted && !isSingleQuoted && !isEscapingSingleQuoted; String prefix = isUnquoted ? "" : originalText.subSequence(0, isEscapingSingleQuoted ? 2 : 1).toString(); String content = isUnquoted ? originalText : originalText.subSequence(isEscapingSingleQuoted ? 2 : 1, originalText.length() - 1).toString(); String suffix = isUnquoted ? "" : originalText.subSequence(originalText.length() - 1, originalText.length()).toString(); TextPreprocessor textProcessor; if (supportEvalEscapes) { if (isEscapingSingleQuoted) { textProcessor = new BashEnhancedTextPreprocessor(TextRange.from(prefix.length(), content.length())); } else if (isSingleQuoted) { //no escape handling for single-quoted strings textProcessor = new BashIdentityTextPreprocessor(TextRange.from(prefix.length(), content.length())); } else { //fallback to simple escape handling textProcessor = new BashSimpleTextPreprocessor(TextRange.from(prefix.length(), content.length())); } } else { textProcessor = new BashIdentityTextPreprocessor(TextRange.from(prefix.length(), content.length())); } StringBuilder unescapedContent = new StringBuilder(content.length()); textProcessor.decode(content, unescapedContent); Lexer lexer = isUnquoted ? def.createLexer(project) : new PrefixSuffixAddingLexer(def.createLexer(project), prefix, TokenType.WHITE_SPACE, suffix, TokenType.WHITE_SPACE); PsiBuilder psiBuilder = new UnescapingPsiBuilder(project, def, lexer, chameleon, originalText, prefix + unescapedContent + suffix, textProcessor); return def.createParser(project).parse(this, psiBuilder).getFirstChildNode(); } }