Add simple_language and updates to simple_language_plugin

This commit is contained in:
JohnHake 2020-02-05 19:28:43 -08:00
parent 308c10991e
commit 0dd8eca961
72 changed files with 3037 additions and 12 deletions

View File

@ -0,0 +1,37 @@
plugins {
id 'java'
id 'org.jetbrains.intellij' version '0.4.15'
}
group 'com.intellij.sdk'
version '2.0.0'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
test {
// Set idea.home.path to the absolute path to the intellij-community source
// on your local machine.
systemProperty "idea.home.path", "/Users/jhake/Documents/source/comm"
}
// Include the generated files in the source set
sourceSets.main.java.srcDirs 'src/main/gen'
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
}
// See https://github.com/JetBrains/gradle-intellij-plugin/
intellij {
version '2019.3.2'
type = 'IC'
plugins 'java'
updateSinceUntilBuild = false
}
patchPluginXml {
version = project.version
}

Binary file not shown.

View File

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

183
simple_language/gradlew vendored Executable file
View File

@ -0,0 +1,183 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# 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
#
# https://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.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

100
simple_language/gradlew.bat vendored Normal file
View File

@ -0,0 +1,100 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -0,0 +1,2 @@
rootProject.name = 'language'

View File

@ -0,0 +1,535 @@
/* The following code was generated by JFlex 1.7.0 tweaked for IntelliJ platform */
package com.intellij.sdk.language;
import com.intellij.lexer.FlexLexer;
import com.intellij.psi.tree.IElementType;
import com.intellij.sdk.language.psi.SimpleTypes;
import com.intellij.psi.TokenType;
/**
* This class is a scanner generated by
* <a href="http://www.jflex.de/">JFlex</a> 1.7.0
* from the specification file <tt>Simple.flex</tt>
*/
class SimpleLexer implements FlexLexer {
/** This character denotes the end of file */
public static final int YYEOF = -1;
/** initial size of the lookahead buffer */
private static final int ZZ_BUFFERSIZE = 16384;
/** lexical states */
public static final int YYINITIAL = 0;
public static final int WAITING_VALUE = 2;
/**
* ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l
* ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l
* at the beginning of a line
* l is of the form l = 2*k, k a non negative integer
*/
private static final int ZZ_LEXSTATE[] = {
0, 0, 1, 1
};
/**
* Translates characters to character classes
* Chosen bits are [9, 6, 6]
* Total runtime size is 1568 bytes
*/
public static int ZZ_CMAP(int ch) {
return ZZ_CMAP_A[(ZZ_CMAP_Y[ZZ_CMAP_Z[ch>>12]|((ch>>6)&0x3f)]<<6)|(ch&0x3f)];
}
/* The ZZ_CMAP_Z table has 272 entries */
static final char ZZ_CMAP_Z[] = zzUnpackCMap(
"\1\0\1\100\1\200\u010d\100");
/* The ZZ_CMAP_Y table has 192 entries */
static final char ZZ_CMAP_Y[] = zzUnpackCMap(
"\1\0\1\1\1\2\175\3\1\4\77\3");
/* The ZZ_CMAP_A table has 320 entries */
static final char ZZ_CMAP_A[] = zzUnpackCMap(
"\11\0\1\4\1\2\1\1\1\5\1\3\22\0\1\7\1\10\1\0\1\10\26\0\1\11\2\0\1\11\36\0\1"+
"\6\50\0\1\1\242\0\2\1\26\0");
/**
* Translates DFA states to action switch labels.
*/
private static final int [] ZZ_ACTION = zzUnpackAction();
private static final String ZZ_ACTION_PACKED_0 =
"\2\0\2\1\1\2\1\3\1\4\1\5\2\6\2\7"+
"\1\3\1\7\1\0\2\4\1\0\1\2\2\6";
private static int [] zzUnpackAction() {
int [] result = new int[21];
int offset = 0;
offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
return result;
}
private static int zzUnpackAction(String packed, int offset, int [] result) {
int i = 0; /* index in packed string */
int j = offset; /* index in unpacked array */
int l = packed.length();
while (i < l) {
int count = packed.charAt(i++);
int value = packed.charAt(i++);
do result[j++] = value; while (--count > 0);
}
return j;
}
/**
* Translates a state to a row index in the transition table
*/
private static final int [] ZZ_ROWMAP = zzUnpackRowMap();
private static final String ZZ_ROWMAP_PACKED_0 =
"\0\0\0\12\0\24\0\36\0\50\0\62\0\74\0\106"+
"\0\120\0\132\0\50\0\144\0\156\0\170\0\62\0\202"+
"\0\214\0\156\0\132\0\226\0\240";
private static int [] zzUnpackRowMap() {
int [] result = new int[21];
int offset = 0;
offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);
return result;
}
private static int zzUnpackRowMap(String packed, int offset, int [] result) {
int i = 0; /* index in packed string */
int j = offset; /* index in unpacked array */
int l = packed.length();
while (i < l) {
int high = packed.charAt(i++) << 16;
result[j++] = high | packed.charAt(i++);
}
return j;
}
/**
* The transition table of the DFA
*/
private static final int [] ZZ_TRANS = zzUnpackTrans();
private static final String ZZ_TRANS_PACKED_0 =
"\1\3\1\4\1\5\1\4\2\5\1\6\1\5\1\7"+
"\1\10\1\11\1\12\1\13\1\12\1\14\1\13\1\15"+
"\1\16\2\11\2\3\1\0\1\3\2\0\1\17\1\0"+
"\1\3\1\0\1\3\1\4\1\5\1\4\2\5\1\17"+
"\1\5\1\3\2\0\5\5\1\0\1\5\11\0\1\3"+
"\2\0\2\7\1\0\1\3\2\20\1\21\1\20\1\7"+
"\1\20\12\0\2\11\1\0\2\11\1\0\1\22\4\11"+
"\1\23\1\5\2\23\1\5\1\22\1\23\3\11\1\24"+
"\1\16\1\24\1\14\1\16\1\22\1\14\5\11\1\25"+
"\6\11\1\0\1\5\1\16\1\5\2\16\1\0\1\16"+
"\2\0\2\20\2\0\10\20\2\0\3\20\1\7\2\20"+
"\1\11\1\24\1\5\2\24\1\5\1\22\1\24\7\11"+
"\1\0\1\22\3\11";
private static int [] zzUnpackTrans() {
int [] result = new int[170];
int offset = 0;
offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result);
return result;
}
private static int zzUnpackTrans(String packed, int offset, int [] result) {
int i = 0; /* index in packed string */
int j = offset; /* index in unpacked array */
int l = packed.length();
while (i < l) {
int count = packed.charAt(i++);
int value = packed.charAt(i++);
value--;
do result[j++] = value; while (--count > 0);
}
return j;
}
/* error codes */
private static final int ZZ_UNKNOWN_ERROR = 0;
private static final int ZZ_NO_MATCH = 1;
private static final int ZZ_PUSHBACK_2BIG = 2;
/* error messages for the codes above */
private static final String[] ZZ_ERROR_MSG = {
"Unknown internal scanner error",
"Error: could not match input",
"Error: pushback value was too large"
};
/**
* ZZ_ATTRIBUTE[aState] contains the attributes of state <code>aState</code>
*/
private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute();
private static final String ZZ_ATTRIBUTE_PACKED_0 =
"\2\0\5\1\1\11\6\1\1\0\2\1\1\0\3\1";
private static int [] zzUnpackAttribute() {
int [] result = new int[21];
int offset = 0;
offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);
return result;
}
private static int zzUnpackAttribute(String packed, int offset, int [] result) {
int i = 0; /* index in packed string */
int j = offset; /* index in unpacked array */
int l = packed.length();
while (i < l) {
int count = packed.charAt(i++);
int value = packed.charAt(i++);
do result[j++] = value; while (--count > 0);
}
return j;
}
/** the input device */
private java.io.Reader zzReader;
/** the current state of the DFA */
private int zzState;
/** the current lexical state */
private int zzLexicalState = YYINITIAL;
/** this buffer contains the current text to be matched and is
the source of the yytext() string */
private CharSequence zzBuffer = "";
/** the textposition at the last accepting state */
private int zzMarkedPos;
/** the current text position in the buffer */
private int zzCurrentPos;
/** startRead marks the beginning of the yytext() string in the buffer */
private int zzStartRead;
/** endRead marks the last character in the buffer, that has been read
from input */
private int zzEndRead;
/**
* zzAtBOL == true <=> the scanner is currently at the beginning of a line
*/
private boolean zzAtBOL = true;
/** zzAtEOF == true <=> the scanner is at the EOF */
private boolean zzAtEOF;
/** denotes if the user-EOF-code has already been executed */
private boolean zzEOFDone;
/**
* Creates a new scanner
*
* @param in the java.io.Reader to read input from.
*/
SimpleLexer(java.io.Reader in) {
this.zzReader = in;
}
/**
* Unpacks the compressed character translation table.
*
* @param packed the packed character translation table
* @return the unpacked character translation table
*/
private static char [] zzUnpackCMap(String packed) {
int size = 0;
for (int i = 0, length = packed.length(); i < length; i += 2) {
size += packed.charAt(i);
}
char[] map = new char[size];
int i = 0; /* index in packed string */
int j = 0; /* index in unpacked array */
while (i < packed.length()) {
int count = packed.charAt(i++);
char value = packed.charAt(i++);
do map[j++] = value; while (--count > 0);
}
return map;
}
public final int getTokenStart() {
return zzStartRead;
}
public final int getTokenEnd() {
return getTokenStart() + yylength();
}
public void reset(CharSequence buffer, int start, int end, int initialState) {
zzBuffer = buffer;
zzCurrentPos = zzMarkedPos = zzStartRead = start;
zzAtEOF = false;
zzAtBOL = true;
zzEndRead = end;
yybegin(initialState);
}
/**
* Refills the input buffer.
*
* @return {@code false}, iff there was new input.
*
* @exception java.io.IOException if any I/O-Error occurs
*/
private boolean zzRefill() throws java.io.IOException {
return true;
}
/**
* Returns the current lexical state.
*/
public final int yystate() {
return zzLexicalState;
}
/**
* Enters a new lexical state
*
* @param newState the new lexical state
*/
public final void yybegin(int newState) {
zzLexicalState = newState;
}
/**
* Returns the text matched by the current regular expression.
*/
public final CharSequence yytext() {
return zzBuffer.subSequence(zzStartRead, zzMarkedPos);
}
/**
* Returns the character at position {@code pos} from the
* matched text.
*
* It is equivalent to yytext().charAt(pos), but faster
*
* @param pos the position of the character to fetch.
* A value from 0 to yylength()-1.
*
* @return the character at position pos
*/
public final char yycharat(int pos) {
return zzBuffer.charAt(zzStartRead+pos);
}
/**
* Returns the length of the matched text region.
*/
public final int yylength() {
return zzMarkedPos-zzStartRead;
}
/**
* Reports an error that occurred while scanning.
*
* In a wellformed scanner (no or only correct usage of
* yypushback(int) and a match-all fallback rule) this method
* will only be called with things that "Can't Possibly Happen".
* If this method is called, something is seriously wrong
* (e.g. a JFlex bug producing a faulty scanner etc.).
*
* Usual syntax/scanner level error handling should be done
* in error fallback rules.
*
* @param errorCode the code of the errormessage to display
*/
private void zzScanError(int errorCode) {
String message;
try {
message = ZZ_ERROR_MSG[errorCode];
}
catch (ArrayIndexOutOfBoundsException e) {
message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR];
}
throw new Error(message);
}
/**
* Pushes the specified amount of characters back into the input stream.
*
* They will be read again by then next call of the scanning method
*
* @param number the number of characters to be read again.
* This number must not be greater than yylength()!
*/
public void yypushback(int number) {
if ( number > yylength() )
zzScanError(ZZ_PUSHBACK_2BIG);
zzMarkedPos -= number;
}
/**
* Contains user EOF-code, which will be executed exactly once,
* when the end of file is reached
*/
private void zzDoEOF() {
if (!zzEOFDone) {
zzEOFDone = true;
}
}
/**
* Resumes scanning until the next regular expression is matched,
* the end of input is encountered or an I/O-Error occurs.
*
* @return the next token
* @exception java.io.IOException if any I/O-Error occurs
*/
public IElementType advance() throws java.io.IOException {
int zzInput;
int zzAction;
// cached fields:
int zzCurrentPosL;
int zzMarkedPosL;
int zzEndReadL = zzEndRead;
CharSequence zzBufferL = zzBuffer;
int [] zzTransL = ZZ_TRANS;
int [] zzRowMapL = ZZ_ROWMAP;
int [] zzAttrL = ZZ_ATTRIBUTE;
while (true) {
zzMarkedPosL = zzMarkedPos;
zzAction = -1;
zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL;
zzState = ZZ_LEXSTATE[zzLexicalState];
// set up zzAction for empty match case:
int zzAttributes = zzAttrL[zzState];
if ( (zzAttributes & 1) == 1 ) {
zzAction = zzState;
}
zzForAction: {
while (true) {
if (zzCurrentPosL < zzEndReadL) {
zzInput = Character.codePointAt(zzBufferL, zzCurrentPosL/*, zzEndReadL*/);
zzCurrentPosL += Character.charCount(zzInput);
}
else if (zzAtEOF) {
zzInput = YYEOF;
break zzForAction;
}
else {
// store back cached positions
zzCurrentPos = zzCurrentPosL;
zzMarkedPos = zzMarkedPosL;
boolean eof = zzRefill();
// get translated positions and possibly new buffer
zzCurrentPosL = zzCurrentPos;
zzMarkedPosL = zzMarkedPos;
zzBufferL = zzBuffer;
zzEndReadL = zzEndRead;
if (eof) {
zzInput = YYEOF;
break zzForAction;
}
else {
zzInput = Character.codePointAt(zzBufferL, zzCurrentPosL/*, zzEndReadL*/);
zzCurrentPosL += Character.charCount(zzInput);
}
}
int zzNext = zzTransL[ zzRowMapL[zzState] + ZZ_CMAP(zzInput) ];
if (zzNext == -1) break zzForAction;
zzState = zzNext;
zzAttributes = zzAttrL[zzState];
if ( (zzAttributes & 1) == 1 ) {
zzAction = zzState;
zzMarkedPosL = zzCurrentPosL;
if ( (zzAttributes & 8) == 8 ) break zzForAction;
}
}
}
// store back cached position
zzMarkedPos = zzMarkedPosL;
if (zzInput == YYEOF && zzStartRead == zzCurrentPos) {
zzAtEOF = true;
zzDoEOF();
return null;
}
else {
switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) {
case 1:
{ yybegin(YYINITIAL); return SimpleTypes.KEY;
}
// fall through
case 8: break;
case 2:
{ yybegin(YYINITIAL); return TokenType.WHITE_SPACE;
}
// fall through
case 9: break;
case 3:
{ return TokenType.BAD_CHARACTER;
}
// fall through
case 10: break;
case 4:
{ yybegin(YYINITIAL); return SimpleTypes.COMMENT;
}
// fall through
case 11: break;
case 5:
{ yybegin(WAITING_VALUE); return SimpleTypes.SEPARATOR;
}
// fall through
case 12: break;
case 6:
{ yybegin(YYINITIAL); return SimpleTypes.VALUE;
}
// fall through
case 13: break;
case 7:
{ yybegin(WAITING_VALUE); return TokenType.WHITE_SPACE;
}
// fall through
case 14: break;
default:
zzScanError(ZZ_NO_MATCH);
}
}
}
}
}

View File

@ -0,0 +1,127 @@
// This is a generated file. Not intended for manual editing.
package com.intellij.sdk.language.parser;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.PsiBuilder.Marker;
import static com.intellij.sdk.language.psi.SimpleTypes.*;
import static com.intellij.lang.parser.GeneratedParserUtilBase.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.lang.ASTNode;
import com.intellij.psi.tree.TokenSet;
import com.intellij.lang.PsiParser;
import com.intellij.lang.LightPsiParser;
@SuppressWarnings({"SimplifiableIfStatement", "UnusedAssignment"})
public class SimpleParser implements PsiParser, LightPsiParser {
public ASTNode parse(IElementType t, PsiBuilder b) {
parseLight(t, b);
return b.getTreeBuilt();
}
public void parseLight(IElementType t, PsiBuilder b) {
boolean r;
b = adapt_builder_(t, b, this, null);
Marker m = enter_section_(b, 0, _COLLAPSE_, null);
r = parse_root_(t, b);
exit_section_(b, 0, m, t, r, true, TRUE_CONDITION);
}
protected boolean parse_root_(IElementType t, PsiBuilder b) {
return parse_root_(t, b, 0);
}
static boolean parse_root_(IElementType t, PsiBuilder b, int l) {
return simpleFile(b, l + 1);
}
/* ********************************************************** */
// property|COMMENT|CRLF
static boolean item_(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "item_")) return false;
boolean r;
Marker m = enter_section_(b);
r = property(b, l + 1);
if (!r) r = consumeToken(b, COMMENT);
if (!r) r = consumeToken(b, CRLF);
exit_section_(b, m, null, r);
return r;
}
/* ********************************************************** */
// (KEY? SEPARATOR VALUE?) | KEY
public static boolean property(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "property")) return false;
boolean r;
Marker m = enter_section_(b, l, _NONE_, PROPERTY, "<property>");
r = property_0(b, l + 1);
if (!r) r = consumeToken(b, KEY);
exit_section_(b, l, m, r, false, recover_property_parser_);
return r;
}
// KEY? SEPARATOR VALUE?
private static boolean property_0(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "property_0")) return false;
boolean r;
Marker m = enter_section_(b);
r = property_0_0(b, l + 1);
r = r && consumeToken(b, SEPARATOR);
r = r && property_0_2(b, l + 1);
exit_section_(b, m, null, r);
return r;
}
// KEY?
private static boolean property_0_0(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "property_0_0")) return false;
consumeToken(b, KEY);
return true;
}
// VALUE?
private static boolean property_0_2(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "property_0_2")) return false;
consumeToken(b, VALUE);
return true;
}
/* ********************************************************** */
// !(KEY|SEPARATOR|COMMENT)
static boolean recover_property(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "recover_property")) return false;
boolean r;
Marker m = enter_section_(b, l, _NOT_);
r = !recover_property_0(b, l + 1);
exit_section_(b, l, m, r, false, null);
return r;
}
// KEY|SEPARATOR|COMMENT
private static boolean recover_property_0(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "recover_property_0")) return false;
boolean r;
r = consumeToken(b, KEY);
if (!r) r = consumeToken(b, SEPARATOR);
if (!r) r = consumeToken(b, COMMENT);
return r;
}
/* ********************************************************** */
// item_*
static boolean simpleFile(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "simpleFile")) return false;
while (true) {
int c = current_position_(b);
if (!item_(b, l + 1)) break;
if (!empty_element_parsed_guard_(b, "simpleFile", c)) break;
}
return true;
}
static final Parser recover_property_parser_ = new Parser() {
public boolean parse(PsiBuilder b, int l) {
return recover_property(b, l + 1);
}
};
}

View File

@ -0,0 +1,23 @@
// This is a generated file. Not intended for manual editing.
package com.intellij.sdk.language.psi;
import java.util.List;
import org.jetbrains.annotations.*;
import com.intellij.psi.PsiElement;
import com.intellij.navigation.ItemPresentation;
public interface SimpleProperty extends SimpleNamedElement {
String getKey();
String getValue();
String getName();
PsiElement setName(String newName);
PsiElement getNameIdentifier();
ItemPresentation getPresentation();
}

View File

@ -0,0 +1,28 @@
// This is a generated file. Not intended for manual editing.
package com.intellij.sdk.language.psi;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.PsiElement;
import com.intellij.lang.ASTNode;
import com.intellij.sdk.language.psi.impl.*;
public interface SimpleTypes {
IElementType PROPERTY = new SimpleElementType("PROPERTY");
IElementType COMMENT = new SimpleTokenType("COMMENT");
IElementType CRLF = new SimpleTokenType("CRLF");
IElementType KEY = new SimpleTokenType("KEY");
IElementType SEPARATOR = new SimpleTokenType("SEPARATOR");
IElementType VALUE = new SimpleTokenType("VALUE");
class Factory {
public static PsiElement createElement(ASTNode node) {
IElementType type = node.getElementType();
if (type == PROPERTY) {
return new SimplePropertyImpl(node);
}
throw new AssertionError("Unknown element type: " + type);
}
}
}

View File

@ -0,0 +1,22 @@
// This is a generated file. Not intended for manual editing.
package com.intellij.sdk.language.psi;
import org.jetbrains.annotations.*;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiElement;
public class SimpleVisitor extends PsiElementVisitor {
public void visitProperty(@NotNull SimpleProperty o) {
visitNamedElement(o);
}
public void visitNamedElement(@NotNull SimpleNamedElement o) {
visitPsiElement(o);
}
public void visitPsiElement(@NotNull PsiElement o) {
visitElement(o);
}
}

View File

@ -0,0 +1,59 @@
// This is a generated file. Not intended for manual editing.
package com.intellij.sdk.language.psi.impl;
import java.util.List;
import org.jetbrains.annotations.*;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.util.PsiTreeUtil;
import static com.intellij.sdk.language.psi.SimpleTypes.*;
import com.intellij.sdk.language.psi.*;
import com.intellij.navigation.ItemPresentation;
public class SimplePropertyImpl extends SimpleNamedElementImpl implements SimpleProperty {
public SimplePropertyImpl(@NotNull ASTNode node) {
super(node);
}
public void accept(@NotNull SimpleVisitor visitor) {
visitor.visitProperty(this);
}
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof SimpleVisitor) accept((SimpleVisitor)visitor);
else super.accept(visitor);
}
@Override
public String getKey() {
return SimplePsiImplUtil.getKey(this);
}
@Override
public String getValue() {
return SimplePsiImplUtil.getValue(this);
}
@Override
public String getName() {
return SimplePsiImplUtil.getName(this);
}
@Override
public PsiElement setName(String newName) {
return SimplePsiImplUtil.setName(this, newName);
}
@Override
public PsiElement getNameIdentifier() {
return SimplePsiImplUtil.getNameIdentifier(this);
}
@Override
public ItemPresentation getPresentation() {
return SimplePsiImplUtil.getPresentation(this);
}
}

View File

@ -0,0 +1,30 @@
{
parserClass="com.intellij.sdk.language.parser.SimpleParser"
extends="com.intellij.extapi.psi.ASTWrapperPsiElement"
psiClassPrefix="Simple"
psiImplClassSuffix="Impl"
psiPackage="com.intellij.sdk.language.psi"
psiImplPackage="com.intellij.sdk.language.psi.impl"
elementTypeHolderClass="com.intellij.sdk.language.psi.SimpleTypes"
elementTypeClass="com.intellij.sdk.language.psi.SimpleElementType"
tokenTypeClass="com.intellij.sdk.language.psi.SimpleTokenType"
psiImplUtilClass="com.intellij.sdk.language.psi.impl.SimplePsiImplUtil"
}
simpleFile ::= item_*
private item_ ::= (property|COMMENT|CRLF)
property ::= (KEY? SEPARATOR VALUE?) | KEY {
pin=3
recoverWhile="recover_property"
mixin="com.intellij.sdk.language.psi.impl.SimpleNamedElementImpl"
implements="com.intellij.sdk.language.psi.SimpleNamedElement"
methods=[getKey getValue getName setName getNameIdentifier getPresentation]
}
private recover_property ::= !(KEY|SEPARATOR|COMMENT)

View File

@ -0,0 +1,44 @@
package com.intellij.sdk.language;
import com.intellij.lexer.FlexLexer;
import com.intellij.psi.tree.IElementType;
import com.intellij.sdk.language.psi.SimpleTypes;
import com.intellij.psi.TokenType;
%%
%class SimpleLexer
%implements FlexLexer
%unicode
%function advance
%type IElementType
%eof{ return;
%eof}
CRLF=\R
WHITE_SPACE=[\ \n\t\f]
FIRST_VALUE_CHARACTER=[^ \n\f\\] | "\\"{CRLF} | "\\".
VALUE_CHARACTER=[^\n\f\\] | "\\"{CRLF} | "\\".
END_OF_LINE_COMMENT=("#"|"!")[^\r\n]*
SEPARATOR=[:=]
KEY_CHARACTER=[^:=\ \n\t\f\\] | "\\ "
%state WAITING_VALUE
%%
<YYINITIAL> {END_OF_LINE_COMMENT} { yybegin(YYINITIAL); return SimpleTypes.COMMENT; }
<YYINITIAL> {KEY_CHARACTER}+ { yybegin(YYINITIAL); return SimpleTypes.KEY; }
<YYINITIAL> {SEPARATOR} { yybegin(WAITING_VALUE); return SimpleTypes.SEPARATOR; }
<WAITING_VALUE> {CRLF}({CRLF}|{WHITE_SPACE})+ { yybegin(YYINITIAL); return TokenType.WHITE_SPACE; }
<WAITING_VALUE> {WHITE_SPACE}+ { yybegin(WAITING_VALUE); return TokenType.WHITE_SPACE; }
<WAITING_VALUE> {FIRST_VALUE_CHARACTER}{VALUE_CHARACTER}* { yybegin(YYINITIAL); return SimpleTypes.VALUE; }
({CRLF}|{WHITE_SPACE})+ { yybegin(YYINITIAL); return TokenType.WHITE_SPACE; }
[^] { return TokenType.BAD_CHARACTER; }

View File

@ -0,0 +1,59 @@
package com.intellij.sdk.language;
import com.intellij.lang.annotation.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.sdk.language.psi.SimpleProperty;
import org.jetbrains.annotations.NotNull;
import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
import java.util.List;
public class SimpleAnnotator implements Annotator {
// Define strings for the Simple language prefix - used for annotations, line markers, etc.
public static final String SIMPLE_PREFIX_STR = "simple";
public static final String SIMPLE_SEPARATOR_STR = ":";
@Override
public void annotate(@NotNull final PsiElement element, @NotNull AnnotationHolder holder) {
// Ensure the Psi element is an expression
if ( !( element instanceof PsiLiteralExpression ) ) return;
// Ensure the Psi element contains a string that starts with the key and separator
PsiLiteralExpression literalExpression = (PsiLiteralExpression) element;
String value = literalExpression.getValue() instanceof String ? (String) literalExpression.getValue() : null;
if ( ( value == null ) || !value.startsWith( SIMPLE_PREFIX_STR + SIMPLE_SEPARATOR_STR ) ) return;
// Define the text ranges (start is inclusive, end is exclusive)
// "simple:key"
// 01234567890
TextRange prefixRange = TextRange.from( element.getTextRange().getStartOffset(), SIMPLE_PREFIX_STR.length() + 1 );
TextRange separatorRange = TextRange.from( prefixRange.getEndOffset(), SIMPLE_SEPARATOR_STR.length() );
TextRange keyRange = new TextRange( separatorRange.getEndOffset(), element.getTextRange().getEndOffset() - 1 );
// Get the list of properties from the Project
String possibleProperties = value.substring( SIMPLE_PREFIX_STR.length() + SIMPLE_SEPARATOR_STR.length() );
Project project = element.getProject();
List< SimpleProperty > properties = SimpleUtil.findProperties( project, possibleProperties );
// Set the annotations using the text ranges.
Annotation keyAnnotation = holder.createInfoAnnotation( prefixRange, null );
keyAnnotation.setTextAttributes( DefaultLanguageHighlighterColors.KEYWORD );
Annotation separatorAnnotation = holder.createInfoAnnotation( separatorRange, null );
separatorAnnotation.setTextAttributes( SimpleSyntaxHighlighter.SEPARATOR );
if ( properties.isEmpty() ) {
// No well-formed property found following the key-separator
Annotation badProperty = holder.createErrorAnnotation( keyRange, "Unresolved property" );
badProperty.setTextAttributes( SimpleSyntaxHighlighter.BAD_CHARACTER );
// ** Tutorial step 18.3 - Add a quick fix for the string containing possible properties
badProperty.registerFix(new SimpleCreatePropertyQuickFix(possibleProperties));
} else {
// Found at least one property
Annotation annotation = holder.createInfoAnnotation( keyRange, null );
annotation.setTextAttributes( SimpleSyntaxHighlighter.VALUE );
}
}
}

View File

@ -0,0 +1,54 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.sdk.language;
import com.intellij.formatting.*;
import com.intellij.lang.ASTNode;
import com.intellij.psi.TokenType;
import com.intellij.psi.formatter.common.AbstractBlock;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
public class SimpleBlock extends AbstractBlock {
private SpacingBuilder spacingBuilder;
protected SimpleBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment,
SpacingBuilder spacingBuilder) {
super(node, wrap, alignment);
this.spacingBuilder = spacingBuilder;
}
@Override
protected List<Block> buildChildren() {
List<Block> blocks = new ArrayList<Block>();
ASTNode child = myNode.getFirstChildNode();
while (child != null) {
if (child.getElementType() != TokenType.WHITE_SPACE) {
Block block = new SimpleBlock(child, Wrap.createWrap(WrapType.NONE, false), Alignment.createAlignment(),
spacingBuilder);
blocks.add(block);
}
child = child.getTreeNext();
}
return blocks;
}
@Override
public Indent getIndent() {
return Indent.getNoneIndent();
}
@Nullable
@Override
public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) {
return spacingBuilder.getSpacing(this, child1, child2);
}
@Override
public boolean isLeaf() {
return myNode.getFirstChildNode() == null;
}
}

View File

@ -0,0 +1,33 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.sdk.language;
import com.intellij.navigation.*;
import com.intellij.openapi.project.Project;
import com.intellij.sdk.language.psi.SimpleProperty;
import org.jetbrains.annotations.NotNull;
import java.util.*;
public class SimpleChooseByNameContributor implements ChooseByNameContributor {
@NotNull
@Override
public String[] getNames(Project project, boolean includeNonProjectItems) {
List<SimpleProperty> properties = SimpleUtil.findProperties(project);
List<String> names = new ArrayList<String>(properties.size());
for (SimpleProperty property : properties) {
if (property.getKey() != null && property.getKey().length() > 0) {
names.add(property.getKey());
}
}
return names.toArray(new String[names.size()]);
}
@NotNull
@Override
public NavigationItem[] getItemsByName(String name, String pattern, Project project, boolean includeNonProjectItems) {
// TODO: include non project items
List<SimpleProperty> properties = SimpleUtil.findProperties(project, name);
return properties.toArray(new NavigationItem[properties.size()]);
}
}

View File

@ -0,0 +1,11 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.sdk.language;
import com.intellij.psi.codeStyle.*;
public class SimpleCodeStyleSettings extends CustomCodeStyleSettings {
public SimpleCodeStyleSettings(CodeStyleSettings settings) {
super("SimpleCodeStyleSettings", settings);
}
}

View File

@ -0,0 +1,37 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.sdk.language;
import com.intellij.application.options.*;
import com.intellij.psi.codeStyle.*;
import org.jetbrains.annotations.*;
public class SimpleCodeStyleSettingsProvider extends CodeStyleSettingsProvider {
@Override
public CustomCodeStyleSettings createCustomSettings(CodeStyleSettings settings) {
return new SimpleCodeStyleSettings(settings);
}
@Nullable
@Override
public String getConfigurableDisplayName() {
return "Simple";
}
@NotNull
public CodeStyleConfigurable createConfigurable(@NotNull CodeStyleSettings settings, @NotNull CodeStyleSettings modelSettings) {
return new CodeStyleAbstractConfigurable(settings, modelSettings, this.getConfigurableDisplayName()) {
@Override
protected CodeStyleAbstractPanel createPanel(CodeStyleSettings settings) {
return new SimpleCodeStyleMainPanel(getCurrentSettings(), settings);
}
};
}
private static class SimpleCodeStyleMainPanel extends TabbedLanguageCodeStylePanel {
public SimpleCodeStyleMainPanel(CodeStyleSettings currentSettings, CodeStyleSettings settings) {
super(SimpleLanguage.INSTANCE, currentSettings, settings);
}
}
}

View File

@ -0,0 +1,73 @@
package com.intellij.sdk.language;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.fileTypes.SyntaxHighlighter;
import com.intellij.openapi.options.colors.*;
import org.jetbrains.annotations.*;
import javax.swing.*;
import java.util.Map;
import static com.intellij.sdk.language.SimpleLanguage.*;
public class SimpleColorSettingsPage implements ColorSettingsPage {
private static final AttributesDescriptor[] DESCRIPTORS = new AttributesDescriptor[]{
new AttributesDescriptor("Key", SimpleSyntaxHighlighter.KEY),
new AttributesDescriptor("Separator", SimpleSyntaxHighlighter.SEPARATOR),
new AttributesDescriptor("Value", SimpleSyntaxHighlighter.VALUE),
new AttributesDescriptor("Bad Value", SimpleSyntaxHighlighter.BAD_CHARACTER)
};
@Nullable
@Override
public Icon getIcon() {
return SimpleIcons.FILE;
}
@NotNull
@Override
public SyntaxHighlighter getHighlighter() {
return new SimpleSyntaxHighlighter();
}
@NotNull
@Override
public String getDemoText() {
return "# You are reading the \".properties\" entry.\n" +
"! The exclamation mark can also mark text as comments.\n" +
"website = http://en.wikipedia.org/\n" +
"language = English\n" +
"# The backslash below tells the application to continue reading\n" +
"# the value onto the next line.\n" +
"message = Welcome to \\\n" +
" Wikipedia!\n" +
"# Add spaces to the key\n" +
"key\\ with\\ spaces = This is the value that could be looked up with the key \"key with spaces\".\n" +
"# Unicode\n" +
"tab : \\u0009";
}
@Nullable
@Override
public Map<String, TextAttributesKey> getAdditionalHighlightingTagToDescriptorMap() {
return null;
}
@NotNull
@Override
public AttributesDescriptor[] getAttributeDescriptors() {
return DESCRIPTORS;
}
@NotNull
@Override
public ColorDescriptor[] getColorDescriptors() {
return ColorDescriptor.EMPTY_ARRAY;
}
@NotNull
@Override
public String getDisplayName() {
return "Simple";
}
}

View File

@ -0,0 +1,38 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.sdk.language;
import com.intellij.lang.Commenter;
import org.jetbrains.annotations.Nullable;
public class SimpleCommenter implements Commenter {
@Nullable
@Override
public String getLineCommentPrefix() {
return "#";
}
@Nullable
@Override
public String getBlockCommentPrefix() {
return "";
}
@Nullable
@Override
public String getBlockCommentSuffix() {
return null;
}
@Nullable
@Override
public String getCommentedBlockCommentPrefix() {
return null;
}
@Nullable
@Override
public String getCommentedBlockCommentSuffix() {
return null;
}
}

View File

@ -0,0 +1,28 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.sdk.language;
import com.intellij.codeInsight.completion.*;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.util.ProcessingContext;
import com.intellij.sdk.language.psi.SimpleTypes;
import org.jetbrains.annotations.NotNull;
public class SimpleCompletionContributor extends CompletionContributor {
public SimpleCompletionContributor() {
// Register the completion providers
extend( CompletionType.BASIC,
PlatformPatterns.psiElement(SimpleTypes.VALUE).withLanguage(SimpleLanguage.INSTANCE),
new CompletionProvider<CompletionParameters>() {
// Define candidate completions
public void addCompletions(@NotNull CompletionParameters parameters,
ProcessingContext context,
@NotNull CompletionResultSet resultSet) {
// Create a completion independent of context for Simple language
resultSet.addElement(LookupElementBuilder.create("Hello"));
}
}
);
}
}

View File

@ -0,0 +1,92 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.sdk.language;
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.Navigatable;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.search.FileTypeIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.IncorrectOperationException;
import com.intellij.sdk.language.psi.SimpleElementFactory;
import com.intellij.sdk.language.psi.SimpleFile;
import com.intellij.sdk.language.psi.SimpleProperty;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
class SimpleCreatePropertyQuickFix extends BaseIntentionAction {
private String key;
SimpleCreatePropertyQuickFix(String key) {
this.key = key;
}
@NotNull
@Override
public String getText() {
return "Create property";
}
@NotNull
@Override
public String getFamilyName() {
return "Simple properties";
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return true;
}
@Override
public void invoke(@NotNull final Project project, final Editor editor, PsiFile file) throws
IncorrectOperationException {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
Collection<VirtualFile> virtualFiles =
FileTypeIndex.getFiles(SimpleFileType.INSTANCE, GlobalSearchScope.allScope(project) );
if (virtualFiles.size() == 1) {
createProperty(project, virtualFiles.iterator().next());
} else {
final FileChooserDescriptor descriptor =
FileChooserDescriptorFactory.createSingleFileDescriptor(SimpleFileType.INSTANCE);
descriptor.setRoots(ProjectUtil.guessProjectDir(project));
final VirtualFile file = FileChooser.chooseFile(descriptor, project, null);
if (file != null) {
createProperty(project, file);
}
}
}
});
}
private void createProperty(final Project project, final VirtualFile file) {
WriteCommandAction.writeCommandAction(project).run(() -> {
SimpleFile simpleFile = (SimpleFile) PsiManager.getInstance(project).findFile(file);
ASTNode lastChildNode = simpleFile.getNode().getLastChildNode();
// TODO: Add another check for CRLF
if (lastChildNode != null/* && !lastChildNode.getElementType().equals(SimpleTypes.CRLF)*/) {
simpleFile.getNode().addChild(SimpleElementFactory.createCRLF(project).getNode());
}
// IMPORTANT: change spaces to escaped spaces or the new node will only have the first word for the key
SimpleProperty property = SimpleElementFactory.createProperty(project, key.replaceAll(" ", "\\\\ "), "");
simpleFile.getNode().addChild(property.getNode());
((Navigatable) property.getLastChild().getNavigationElement()).navigate(true);
FileEditorManager.getInstance(project).getSelectedTextEditor().getCaretModel().moveCaretRelatively(2, 0, false, false, false);
});
}
}

View File

@ -0,0 +1,39 @@
package com.intellij.sdk.language;
import com.intellij.openapi.fileTypes.LanguageFileType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
public class SimpleFileType extends LanguageFileType {
public static final SimpleFileType INSTANCE = new SimpleFileType();
private SimpleFileType() {
super(SimpleLanguage.INSTANCE);
}
@NotNull
@Override
public String getName() {
return "Simple file";
}
@NotNull
@Override
public String getDescription() {
return "Simple language file";
}
@NotNull
@Override
public String getDefaultExtension() {
return "simple";
}
@Nullable
@Override
public Icon getIcon() {
return SimpleIcons.FILE;
}
}

View File

@ -0,0 +1,16 @@
package com.intellij.sdk.language;
import com.intellij.openapi.fileTypes.FileTypeConsumer;
import com.intellij.openapi.fileTypes.FileTypeFactory;
import org.jetbrains.annotations.NotNull;
/**
* Note: This class is only used with the fileTypeFactory extension point
* for versions of the IntelliJ Platform prior to v2019.2
*/
public class SimpleFileTypeFactory extends FileTypeFactory {
@Override
public void createFileTypes(@NotNull FileTypeConsumer fileTypeConsumer) {
fileTypeConsumer.consume(SimpleFileType.INSTANCE);
}
}

View File

@ -0,0 +1,63 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.sdk.language;
import com.intellij.lang.cacheBuilder.*;
import com.intellij.lang.findUsages.FindUsagesProvider;
import com.intellij.psi.*;
import com.intellij.psi.tree.TokenSet;
import com.intellij.sdk.language.psi.*;
import org.jetbrains.annotations.*;
import static com.intellij.sdk.language.SimpleAnnotator.*;
public class SimpleFindUsagesProvider implements FindUsagesProvider {
@Nullable
@Override
public WordsScanner getWordsScanner() {
return new DefaultWordsScanner(new SimpleLexerAdapter(),
TokenSet.create(SimpleTypes.KEY),
TokenSet.create(SimpleTypes.COMMENT),
TokenSet.EMPTY);
}
@Override
public boolean canFindUsagesFor(@NotNull PsiElement psiElement) {
return psiElement instanceof PsiNamedElement;
}
@Nullable
@Override
public String getHelpId(@NotNull PsiElement psiElement) {
return null;
}
@NotNull
@Override
public String getType(@NotNull PsiElement element) {
if (element instanceof SimpleProperty) {
return "simple property";
} else {
return "";
}
}
@NotNull
@Override
public String getDescriptiveName(@NotNull PsiElement element) {
if (element instanceof SimpleProperty) {
return ((SimpleProperty) element).getKey();
} else {
return "";
}
}
@NotNull
@Override
public String getNodeText(@NotNull PsiElement element, boolean useFullName) {
if (element instanceof SimpleProperty) {
return ((SimpleProperty) element).getKey() + SIMPLE_SEPARATOR_STR + ((SimpleProperty) element).getValue();
} else {
return "";
}
}
}

View File

@ -0,0 +1,78 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.sdk.language;
import com.intellij.lang.ASTNode;
import com.intellij.lang.folding.*;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.project.*;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.sdk.language.psi.SimpleProperty;
import org.jetbrains.annotations.*;
import static com.intellij.sdk.language.SimpleAnnotator.*;
import java.util.*;
public class SimpleFoldingBuilder extends FoldingBuilderEx implements DumbAware {
@NotNull
@Override
public FoldingDescriptor[] buildFoldRegions(@NotNull PsiElement root, @NotNull Document document, boolean quick) {
// Initialize the group of folding regions that will expand/collapse together.
FoldingGroup group = FoldingGroup.newGroup(SIMPLE_PREFIX_STR);
// Initialize the list of folding regions
List< FoldingDescriptor > descriptors = new ArrayList< FoldingDescriptor >();
// Get a collection of the literal expressions in the document below root
Collection< PsiLiteralExpression > literalExpressions =
PsiTreeUtil.findChildrenOfType(root, PsiLiteralExpression.class);
// Evaluate the collection, using only Simple language literalExpressions
for ( final PsiLiteralExpression literalExpression : literalExpressions ) {
String value = literalExpression.getValue() instanceof String ? (String) literalExpression.getValue() : null;
if ( value != null && value.startsWith(SIMPLE_PREFIX_STR + SIMPLE_SEPARATOR_STR) ) {
Project project = literalExpression.getProject();
String key = value.substring(SIMPLE_PREFIX_STR.length() + SIMPLE_SEPARATOR_STR.length());
// Get a list of properties for the project
final List< SimpleProperty > properties = SimpleUtil.findProperties(project, key);
if ( properties.size() == 1 ) {
// Add a folding descriptor for the literal expression at this node.
descriptors.add(new FoldingDescriptor(literalExpression.getNode(),
new TextRange(literalExpression.getTextRange().getStartOffset() + 1,
literalExpression.getTextRange().getEndOffset() - 1),
group) );
}
}
}
return descriptors.toArray(new FoldingDescriptor[descriptors.size()]);
}
/**
* Gets the Simple Language 'value' string corresponding to the 'key'
* @param node Node corresponding to PsiLiteralExpression containing a string in the format
* SIMPLE_PREFIX_STR + SIMPLE_SEPARATOR_STR + Key, where Key is
* defined by the Simple language file.
* @return String corresponding to the "website" key.
*/
@Nullable
@Override
public String getPlaceholderText(@NotNull ASTNode node) {
String retTxt = "...";
if ( node.getPsi() instanceof PsiLiteralExpression ) {
PsiLiteralExpression nodeElement = (PsiLiteralExpression) node.getPsi();
String key = ((String) nodeElement.getValue()).substring(SIMPLE_PREFIX_STR.length() + SIMPLE_SEPARATOR_STR.length());
final List< SimpleProperty > properties = SimpleUtil.findProperties(nodeElement.getProject(), key);
String place = properties.get(0).getValue();
// IMPORTANT: keys can come with no values, so a test for null is needed
// IMPORTANT: Convert embedded \n to backslash n, so that the string will look
// like it has LF embedded in it and embedded " to escaped "
return place == null ? retTxt : place.replaceAll("\n", "\\n").replaceAll("\"", "\\\\\"");
}
return retTxt;
}
@Override
public boolean isCollapsedByDefault(@NotNull ASTNode node) {
return true;
}
}

View File

@ -0,0 +1,39 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.sdk.language;
import com.intellij.formatting.*;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.sdk.language.psi.SimpleTypes;
import org.jetbrains.annotations.*;
public class SimpleFormattingModelBuilder implements FormattingModelBuilder {
@NotNull
@Override
public FormattingModel createModel(PsiElement element, CodeStyleSettings settings) {
return FormattingModelProvider
.createFormattingModelForPsiFile(element.getContainingFile(),
new SimpleBlock(element.getNode(),
Wrap.createWrap(WrapType.NONE, false),
Alignment.createAlignment(),
createSpaceBuilder(settings)),
settings);
}
private static SpacingBuilder createSpaceBuilder(CodeStyleSettings settings) {
return new SpacingBuilder(settings, SimpleLanguage.INSTANCE)
.around(SimpleTypes.SEPARATOR)
.spaceIf(settings.getCommonSettings(SimpleLanguage.INSTANCE.getID()).SPACE_AROUND_ASSIGNMENT_OPERATORS)
.before(SimpleTypes.PROPERTY)
.none();
}
@Nullable
@Override
public TextRange getRangeAffectingIndent(PsiFile file, int offset, ASTNode elementAtOffset) {
return null;
}
}

View File

@ -0,0 +1,9 @@
package com.intellij.sdk.language;
import com.intellij.openapi.util.IconLoader;
import javax.swing.*;
public class SimpleIcons {
public static final Icon FILE = IconLoader.getIcon("/icons/jar-gray.png");
}

View File

@ -0,0 +1,11 @@
package com.intellij.sdk.language;
import com.intellij.lang.Language;
public class SimpleLanguage extends Language {
public static final SimpleLanguage INSTANCE = new SimpleLanguage();
private SimpleLanguage() {
super("Simple");
}
}

View File

@ -0,0 +1,42 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.sdk.language;
import com.intellij.lang.Language;
import com.intellij.psi.codeStyle.*;
import org.jetbrains.annotations.NotNull;
public class SimpleLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSettingsProvider {
@NotNull
@Override
public Language getLanguage() {
return SimpleLanguage.INSTANCE;
}
@Override
public void customizeSettings(@NotNull CodeStyleSettingsCustomizable consumer, @NotNull SettingsType settingsType) {
if (settingsType == SettingsType.SPACING_SETTINGS) {
consumer.showStandardOptions("SPACE_AROUND_ASSIGNMENT_OPERATORS");
consumer.renameStandardOption("SPACE_AROUND_ASSIGNMENT_OPERATORS", "Separator");
} else if (settingsType == SettingsType.BLANK_LINES_SETTINGS) {
consumer.showStandardOptions("KEEP_BLANK_LINES_IN_CODE");
}
}
@Override
public String getCodeSample(@NotNull SettingsType settingsType) {
return "# You are reading the \".properties\" entry.\n" +
"! The exclamation mark can also mark text as comments.\n" +
"website = http://en.wikipedia.org/\n" +
"\n" +
"language = English\n" +
"# The backslash below tells the application to continue reading\n" +
"# the value onto the next line.\n" +
"message = Welcome to \\\n" +
" Wikipedia!\n" +
"# Add spaces to the key\n" +
"key\\ with\\ spaces = This is the value that could be looked up with the key \"key with spaces\".\n" +
"# Unicode\n" +
"tab : \\u0009";
}
}

View File

@ -0,0 +1,11 @@
package com.intellij.sdk.language;
import com.intellij.lexer.FlexAdapter;
import java.io.Reader;
public class SimpleLexerAdapter extends FlexAdapter {
public SimpleLexerAdapter() {
super(new SimpleLexer((Reader) null));
}
}

View File

@ -0,0 +1,40 @@
package com.intellij.sdk.language;
import com.intellij.codeInsight.daemon.*;
import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.java.PsiJavaTokenImpl;
import com.intellij.sdk.language.psi.SimpleProperty;
import org.jetbrains.annotations.NotNull;
import static com.intellij.sdk.language.SimpleAnnotator.*;
import java.util.*;
public class SimpleLineMarkerProvider extends RelatedItemLineMarkerProvider {
@Override
protected void collectNavigationMarkers( @NotNull PsiElement element,
@NotNull Collection< ? super RelatedItemLineMarkerInfo > result ) {
// This must be an element with a literal expression as a parent
if ( !(element instanceof PsiJavaTokenImpl) || !(element.getParent() instanceof PsiLiteralExpression) ) return;
// The literal expression must start with the Simple language literal expression
PsiLiteralExpression literalExpression = (PsiLiteralExpression) element.getParent();
String value = literalExpression.getValue() instanceof String ? (String) literalExpression.getValue() : null;
if ( ( value == null ) || !value.startsWith( SIMPLE_PREFIX_STR + SIMPLE_SEPARATOR_STR ) ) return;
// Get the Simple language property usage
Project project = element.getProject();
String possibleProperties = value.substring( SIMPLE_PREFIX_STR.length()+SIMPLE_SEPARATOR_STR.length() );
final List< SimpleProperty > properties = SimpleUtil.findProperties( project, possibleProperties );
if ( properties.size() > 0 ) {
// Add the property to a collection of line marker info
NavigationGutterIconBuilder< PsiElement > builder =
NavigationGutterIconBuilder.create( SimpleIcons.FILE )
.setTargets( properties )
.setTooltipText( "Navigate to Simple language property" );
result.add( builder.createLineMarkerInfo( element ) );
}
}
}

View File

@ -0,0 +1,68 @@
package com.intellij.sdk.language;
import com.intellij.lang.*;
import com.intellij.lexer.Lexer;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.tree.*;
import com.intellij.sdk.language.parser.SimpleParser;
import com.intellij.sdk.language.psi.*;
import org.jetbrains.annotations.NotNull;
public class SimpleParserDefinition implements ParserDefinition {
public static final TokenSet WHITE_SPACES = TokenSet.create(TokenType.WHITE_SPACE);
public static final TokenSet COMMENTS = TokenSet.create(SimpleTypes.COMMENT);
public static final IFileElementType FILE = new IFileElementType(SimpleLanguage.INSTANCE);
@NotNull
@Override
public Lexer createLexer(Project project) {
return new SimpleLexerAdapter();
}
@NotNull
@Override
public TokenSet getWhitespaceTokens() {
return WHITE_SPACES;
}
@NotNull
@Override
public TokenSet getCommentTokens() {
return COMMENTS;
}
@NotNull
@Override
public TokenSet getStringLiteralElements() {
return TokenSet.EMPTY;
}
@NotNull
@Override
public PsiParser createParser(final Project project) {
return new SimpleParser();
}
@Override
public IFileElementType getFileNodeType() {
return FILE;
}
@Override
public PsiFile createFile(FileViewProvider viewProvider) {
return new SimpleFile(viewProvider);
}
@Override
public SpaceRequirements spaceExistenceTypeBetweenTokens(ASTNode left, ASTNode right) {
return SpaceRequirements.MAY;
}
@NotNull
@Override
public PsiElement createElement(ASTNode node) {
return SimpleTypes.Factory.createElement(node);
}
}

View File

@ -0,0 +1,20 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.sdk.language;
import com.intellij.lang.refactoring.RefactoringSupportProvider;
import com.intellij.psi.PsiElement;
import com.intellij.sdk.language.psi.SimpleProperty;
import org.jetbrains.annotations.*;
public class SimpleRefactoringSupportProvider extends RefactoringSupportProvider {
@Override
public boolean isMemberInplaceRenameAvailable(@NotNull PsiElement elementToRename, @Nullable PsiElement context) {
return (elementToRename instanceof SimpleProperty);
}
}
/*
2020-01-10 21:59:36,392 [ 74521] WARN - name.RenamePsiElementProcessor - org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinTypeParameterProcessor overrides deprecated findReferences(..).
Override findReferences(PsiElement, SearchScope, boolean) instead.
*/

View File

@ -0,0 +1,57 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.sdk.language;
import com.intellij.codeInsight.lookup.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.sdk.language.psi.SimpleProperty;
import org.jetbrains.annotations.*;
import java.util.*;
public class SimpleReference extends PsiReferenceBase<PsiElement> implements PsiPolyVariantReference {
private String key;
public SimpleReference(@NotNull PsiElement element, TextRange textRange) {
super(element, textRange);
key = element.getText().substring(textRange.getStartOffset(), textRange.getEndOffset());
}
@NotNull
@Override
public ResolveResult[] multiResolve(boolean incompleteCode) {
Project project = myElement.getProject();
final List<SimpleProperty> properties = SimpleUtil.findProperties(project, key);
List<ResolveResult> results = new ArrayList<ResolveResult>();
for (SimpleProperty property : properties) {
results.add(new PsiElementResolveResult(property));
}
return results.toArray(new ResolveResult[results.size()]);
}
@Nullable
@Override
public PsiElement resolve() {
ResolveResult[] resolveResults = multiResolve(false);
return resolveResults.length == 1 ? resolveResults[0].getElement() : null;
}
@NotNull
@Override
public Object[] getVariants() {
Project project = myElement.getProject();
List<SimpleProperty> properties = SimpleUtil.findProperties(project);
List<LookupElement> variants = new ArrayList<LookupElement>();
for (final SimpleProperty property : properties) {
if (property.getKey() != null && property.getKey().length() > 0) {
variants.add(LookupElementBuilder
.create(property).withIcon(SimpleIcons.FILE)
.withTypeText(property.getContainingFile().getName())
);
}
}
return variants.toArray();
}
}

View File

@ -0,0 +1,34 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.sdk.language;
import com.intellij.openapi.util.TextRange;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.psi.*;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
import static com.intellij.sdk.language.SimpleAnnotator.*;
public class SimpleReferenceContributor extends PsiReferenceContributor {
@Override
public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) {
registrar.registerReferenceProvider( PlatformPatterns.psiElement( PsiLiteralExpression.class ),
new PsiReferenceProvider() {
@NotNull
@Override
public PsiReference[] getReferencesByElement(@NotNull PsiElement element,
@NotNull ProcessingContext context) {
PsiLiteralExpression literalExpression = (PsiLiteralExpression) element;
String value = literalExpression.getValue() instanceof String ?
(String) literalExpression.getValue() : null;
if ( ( value != null && value.startsWith( SIMPLE_PREFIX_STR + SIMPLE_SEPARATOR_STR ) ) ) {
TextRange property = new TextRange( SIMPLE_PREFIX_STR.length() + SIMPLE_SEPARATOR_STR.length() + 1,
value.length() + 1 );
return new PsiReference[]{ new SimpleReference( element, property ) };
}
return PsiReference.EMPTY_ARRAY;
}
} );
}
}

View File

@ -0,0 +1,74 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.sdk.language;
import com.intellij.ide.projectView.PresentationData;
import com.intellij.ide.structureView.StructureViewTreeElement;
import com.intellij.ide.util.treeView.smartTree.SortableTreeElement;
import com.intellij.ide.util.treeView.smartTree.TreeElement;
import com.intellij.navigation.ItemPresentation;
import com.intellij.psi.NavigatablePsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.sdk.language.psi.SimpleFile;
import com.intellij.sdk.language.psi.SimpleProperty;
import com.intellij.sdk.language.psi.impl.SimplePropertyImpl;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
public class SimpleStructureViewElement implements StructureViewTreeElement, SortableTreeElement {
private NavigatablePsiElement element;
public SimpleStructureViewElement(NavigatablePsiElement element) {
this.element = element;
}
@Override
public Object getValue() {
return element;
}
@Override
public void navigate(boolean requestFocus) {
element.navigate(requestFocus);
}
@Override
public boolean canNavigate() {
return element.canNavigate();
}
@Override
public boolean canNavigateToSource() {
return element.canNavigateToSource();
}
@NotNull
@Override
public String getAlphaSortKey() {
String name = element.getName();
return name != null ? name : "";
}
@NotNull
@Override
public ItemPresentation getPresentation() {
ItemPresentation presentation = element.getPresentation();
return presentation != null ? presentation : new PresentationData();
}
@Override
public TreeElement[] getChildren() {
if (element instanceof SimpleFile) {
SimpleProperty[] properties = PsiTreeUtil.getChildrenOfType(element, SimpleProperty.class);
List<TreeElement> treeElements = new ArrayList<TreeElement>(properties.length);
for (SimpleProperty property : properties) {
treeElements.add(new SimpleStructureViewElement((SimplePropertyImpl) property));
}
return treeElements.toArray(new TreeElement[treeElements.size()]);
} else {
return EMPTY_ARRAY;
}
}
}

View File

@ -0,0 +1,23 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.sdk.language;
import com.intellij.ide.structureView.*;
import com.intellij.lang.PsiStructureViewFactory;
import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.*;
public class SimpleStructureViewFactory implements PsiStructureViewFactory {
@Nullable
@Override
public StructureViewBuilder getStructureViewBuilder(final PsiFile psiFile) {
return new TreeBasedStructureViewBuilder() {
@NotNull
@Override
public StructureViewModel createStructureViewModel(@Nullable Editor editor) {
return new SimpleStructureViewModel(psiFile);
}
};
}
}

View File

@ -0,0 +1,32 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.sdk.language;
import com.intellij.ide.structureView.*;
import com.intellij.ide.util.treeView.smartTree.Sorter;
import com.intellij.psi.PsiFile;
import com.intellij.sdk.language.psi.SimpleFile;
import org.jetbrains.annotations.NotNull;
public class SimpleStructureViewModel extends StructureViewModelBase implements
StructureViewModel.ElementInfoProvider {
public SimpleStructureViewModel(PsiFile psiFile) {
super(psiFile, new SimpleStructureViewElement(psiFile));
}
@NotNull
public Sorter[] getSorters() {
return new Sorter[]{Sorter.ALPHA_SORTER};
}
@Override
public boolean isAlwaysShowsPlus(StructureViewTreeElement element) {
return false;
}
@Override
public boolean isAlwaysLeaf(StructureViewTreeElement element) {
return element instanceof SimpleFile;
}
}

View File

@ -0,0 +1,57 @@
package com.intellij.sdk.language;
import com.intellij.lexer.Lexer;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.fileTypes.SyntaxHighlighterBase;
import com.intellij.psi.TokenType;
import com.intellij.psi.tree.IElementType;
import com.intellij.sdk.language.psi.SimpleTypes;
import org.jetbrains.annotations.NotNull;
import static com.intellij.openapi.editor.colors.TextAttributesKey.createTextAttributesKey;
public class SimpleSyntaxHighlighter extends SyntaxHighlighterBase {
public static final TextAttributesKey SEPARATOR =
createTextAttributesKey("SIMPLE_SEPARATOR", DefaultLanguageHighlighterColors.OPERATION_SIGN);
public static final TextAttributesKey KEY =
createTextAttributesKey("SIMPLE_KEY", DefaultLanguageHighlighterColors.KEYWORD);
public static final TextAttributesKey VALUE =
createTextAttributesKey("SIMPLE_VALUE", DefaultLanguageHighlighterColors.STRING);
public static final TextAttributesKey COMMENT =
createTextAttributesKey("SIMPLE_COMMENT", DefaultLanguageHighlighterColors.LINE_COMMENT);
public static final TextAttributesKey BAD_CHARACTER =
createTextAttributesKey("SIMPLE_BAD_CHARACTER", HighlighterColors.BAD_CHARACTER);
private static final TextAttributesKey[] BAD_CHAR_KEYS = new TextAttributesKey[]{BAD_CHARACTER};
private static final TextAttributesKey[] SEPARATOR_KEYS = new TextAttributesKey[]{SEPARATOR};
private static final TextAttributesKey[] KEY_KEYS = new TextAttributesKey[]{KEY};
private static final TextAttributesKey[] VALUE_KEYS = new TextAttributesKey[]{VALUE};
private static final TextAttributesKey[] COMMENT_KEYS = new TextAttributesKey[]{COMMENT};
private static final TextAttributesKey[] EMPTY_KEYS = new TextAttributesKey[0];
@NotNull
@Override
public Lexer getHighlightingLexer() {
return new SimpleLexerAdapter();
}
@NotNull
@Override
public TextAttributesKey[] getTokenHighlights(IElementType tokenType) {
if (tokenType.equals(SimpleTypes.SEPARATOR)) {
return SEPARATOR_KEYS;
} else if (tokenType.equals(SimpleTypes.KEY)) {
return KEY_KEYS;
} else if (tokenType.equals(SimpleTypes.VALUE)) {
return VALUE_KEYS;
} else if (tokenType.equals(SimpleTypes.COMMENT)) {
return COMMENT_KEYS;
} else if (tokenType.equals(TokenType.BAD_CHARACTER)) {
return BAD_CHAR_KEYS;
} else {
return EMPTY_KEYS;
}
}
}

View File

@ -0,0 +1,14 @@
package com.intellij.sdk.language;
import com.intellij.openapi.fileTypes.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
public class SimpleSyntaxHighlighterFactory extends SyntaxHighlighterFactory {
@NotNull
@Override
public SyntaxHighlighter getSyntaxHighlighter(Project project, VirtualFile virtualFile) {
return new SimpleSyntaxHighlighter();
}
}

View File

@ -0,0 +1,54 @@
package com.intellij.sdk.language;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.search.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.indexing.FileBasedIndex;
import com.intellij.sdk.language.psi.*;
import java.util.*;
public class SimpleUtil {
// Searches the entire project for Simple language files with instances of the Simple property
public static List<SimpleProperty> findProperties(Project project, String key) {
List<SimpleProperty> result = null;
Collection<VirtualFile> virtualFiles =
FileTypeIndex.getFiles(SimpleFileType.INSTANCE, GlobalSearchScope.allScope(project));
for (VirtualFile virtualFile : virtualFiles) {
SimpleFile simpleFile = (SimpleFile) PsiManager.getInstance(project).findFile(virtualFile);
if (simpleFile != null) {
SimpleProperty[] properties = PsiTreeUtil.getChildrenOfType(simpleFile, SimpleProperty.class);
if (properties != null) {
for (SimpleProperty property : properties) {
if (key.equals(property.getKey())) {
if (result == null) {
result = new ArrayList<SimpleProperty>();
}
result.add(property);
}
}
}
}
}
return result != null ? result : Collections.<SimpleProperty>emptyList();
}
public static List<SimpleProperty> findProperties(Project project) {
List<SimpleProperty> result = new ArrayList<SimpleProperty>();
Collection<VirtualFile> virtualFiles =
FileTypeIndex.getFiles(SimpleFileType.INSTANCE, GlobalSearchScope.allScope(project));
for (VirtualFile virtualFile : virtualFiles) {
SimpleFile simpleFile = (SimpleFile) PsiManager.getInstance(project).findFile(virtualFile);
if (simpleFile != null) {
SimpleProperty[] properties = PsiTreeUtil.getChildrenOfType(simpleFile, SimpleProperty.class);
if (properties != null) {
Collections.addAll(result, properties);
}
}
}
return result;
}
}

View File

@ -0,0 +1,29 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.sdk.language.psi;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.sdk.language.SimpleFileType;
public class SimpleElementFactory {
public static SimpleProperty createProperty(Project project, String name) {
final SimpleFile file = createFile(project, name);
return (SimpleProperty) file.getFirstChild();
}
public static SimpleProperty createProperty(Project project, String name, String value) {
final SimpleFile file = createFile(project, name + " = " + value);
return (SimpleProperty) file.getFirstChild();
}
public static PsiElement createCRLF(Project project) {
final SimpleFile file = createFile(project, "\n");
return file.getFirstChild();
}
public static SimpleFile createFile(Project project, String text) {
String name = "dummy.simple";
return (SimpleFile) PsiFileFactory.getInstance( project).createFileFromText(name, SimpleFileType.INSTANCE, text);
}
}

View File

@ -0,0 +1,12 @@
package com.intellij.sdk.language.psi;
import com.intellij.psi.tree.IElementType;
import com.intellij.sdk.language.SimpleLanguage;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
public class SimpleElementType extends IElementType {
public SimpleElementType( @NotNull @NonNls String debugName) {
super(debugName, SimpleLanguage.INSTANCE);
}
}

View File

@ -0,0 +1,31 @@
package com.intellij.sdk.language.psi;
import com.intellij.extapi.psi.PsiFileBase;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.psi.FileViewProvider;
import com.intellij.sdk.language.*;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
public class SimpleFile extends PsiFileBase {
public SimpleFile(@NotNull FileViewProvider viewProvider) {
super(viewProvider, SimpleLanguage.INSTANCE);
}
@NotNull
@Override
public FileType getFileType() {
return SimpleFileType.INSTANCE;
}
@Override
public String toString() {
return "Simple File";
}
@Override
public Icon getIcon(int flags) {
return super.getIcon(flags);
}
}

View File

@ -0,0 +1,8 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.sdk.language.psi;
import com.intellij.psi.PsiNameIdentifierOwner;
public interface SimpleNamedElement extends PsiNameIdentifierOwner {
}

View File

@ -0,0 +1,16 @@
package com.intellij.sdk.language.psi;
import com.intellij.psi.tree.IElementType;
import com.intellij.sdk.language.SimpleLanguage;
import org.jetbrains.annotations.*;
public class SimpleTokenType extends IElementType {
public SimpleTokenType(@NotNull @NonNls String debugName) {
super(debugName, SimpleLanguage.INSTANCE);
}
@Override
public String toString() {
return "SimpleTokenType." + super.toString();
}
}

View File

@ -0,0 +1,14 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.sdk.language.psi.impl;
import com.intellij.extapi.psi.ASTWrapperPsiElement;
import com.intellij.lang.ASTNode;
import com.intellij.sdk.language.psi.SimpleNamedElement;
import org.jetbrains.annotations.NotNull;
public abstract class SimpleNamedElementImpl extends ASTWrapperPsiElement implements SimpleNamedElement {
public SimpleNamedElementImpl(@NotNull ASTNode node) {
super(node);
}
}

View File

@ -0,0 +1,79 @@
package com.intellij.sdk.language.psi.impl;
import com.intellij.lang.ASTNode;
import com.intellij.navigation.ItemPresentation;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.sdk.language.SimpleIcons;
import com.intellij.sdk.language.psi.*;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
public class SimplePsiImplUtil {
public static String getKey(SimpleProperty element) {
ASTNode keyNode = element.getNode().findChildByType(SimpleTypes.KEY);
if (keyNode != null) {
// IMPORTANT: Convert embedded escaped spaces to simple spaces
return keyNode.getText().replaceAll("\\\\ ", " ");
} else {
return null;
}
}
public static String getValue(SimpleProperty element) {
ASTNode valueNode = element.getNode().findChildByType(SimpleTypes.VALUE);
if (valueNode != null) {
return valueNode.getText();
} else {
return null;
}
}
public static String getName(SimpleProperty element) {
return getKey(element);
}
public static PsiElement setName(SimpleProperty element, String newName) {
ASTNode keyNode = element.getNode().findChildByType(SimpleTypes.KEY);
if (keyNode != null) {
SimpleProperty property = SimpleElementFactory.createProperty(element.getProject(), newName);
ASTNode newKeyNode = property.getFirstChild().getNode();
element.getNode().replaceChild(keyNode, newKeyNode);
}
return element;
}
public static PsiElement getNameIdentifier( SimpleProperty element) {
ASTNode keyNode = element.getNode().findChildByType(SimpleTypes.KEY);
if (keyNode != null) {
return keyNode.getPsi();
} else {
return null;
}
}
public static ItemPresentation getPresentation( final SimpleProperty element) {
return new ItemPresentation() {
@Nullable
@Override
public String getPresentableText() {
return element.getKey();
}
@Nullable
@Override
public String getLocationString() {
PsiFile containingFile = element.getContainingFile();
return containingFile == null ? null : containingFile.getName();
}
@Nullable
@Override
public Icon getIcon( boolean unused) {
return SimpleIcons.FILE;
}
};
}
}

View File

@ -0,0 +1,66 @@
<!-- Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
<idea-plugin>
<!-- Unique id for this plugin. Must stay constant for the life of the plugin. -->
<id>com.intellij.sdk.simple_language</id>
<!-- Text to display as name on Preferences/Settings | Plugin page -->
<name>SDK: Simple Language Sample Project</name>
<!-- The version of this plugin -->
<version>2.0.0</version>
<!-- Compatible with the following versions of IntelliJ Platform
At least 2019.2 is required. Otherwise, a FileTypeFactor must be registered as an extension.
See the extensions section below. -->
<idea-version since-build="192.2"/>
<!-- Product and plugin compatibility requirements -->
<depends>com.intellij.modules.platform</depends>
<depends>com.intellij.modules.java</depends>
<!-- Text to display as description on Preferences/Settings | Plugin page -->
<description>
<![CDATA[
Demonstrates how to add custom language support to an IntelliJ Platform-based IDE. <br>Defines a new language, <i>Simple language</i> with support for syntax highlighting, annotations, code completion, and other features.
<br>See the <a href="https://www.jetbrains.org/intellij/sdk/docs/tutorials/custom_language_support_tutorial.html">Custom Language Tutorial</a> for more information.
]]>
</description>
<change-notes>
<![CDATA[
<ul>
<li><b>2.0.0</b> Convert to Gradle-based plugin.</li>
<li><b>1.0.0</b> Release 2018.3 and earlier.</li>
</ul>
]]>
</change-notes>
<!-- Text to display as company information on Preferences/Settings | Plugin page -->
<vendor url="https://plugins.jetbrains.com">IntelliJ Platform SDK</vendor>
<extensions defaultExtensionNs="com.intellij">
<fileType name="Simple file" implementationClass="com.intellij.sdk.language.SimpleFileType" fieldName="INSTANCE"
language="Simple" extensions="simple"/>
<!-- Only required for versions of the IntelliJ Platform prior to v2019.2.
<fileTypeFactory implementation="com.intellij.sdk.language.SimpleFileTypeFactory"/>
-->
<lang.parserDefinition language="Simple" implementationClass="com.intellij.sdk.language.SimpleParserDefinition"/>
<lang.syntaxHighlighterFactory language="Simple" implementationClass="com.intellij.sdk.language.SimpleSyntaxHighlighterFactory"/>
<colorSettingsPage implementation="com.intellij.sdk.language.SimpleColorSettingsPage"/>
<annotator language="JAVA" implementationClass="com.intellij.sdk.language.SimpleAnnotator"/>
<codeInsight.lineMarkerProvider language="JAVA" implementationClass="com.intellij.sdk.language.SimpleLineMarkerProvider"/>
<completion.contributor language="Simple" implementationClass="com.intellij.sdk.language.SimpleCompletionContributor"/>
<psi.referenceContributor implementation="com.intellij.sdk.language.SimpleReferenceContributor"/>
<lang.refactoringSupport language="Simple" implementationClass="com.intellij.sdk.language.SimpleRefactoringSupportProvider"/>
<lang.findUsagesProvider language="Simple" implementationClass="com.intellij.sdk.language.SimpleFindUsagesProvider"/>
<lang.foldingBuilder language="JAVA" implementationClass="com.intellij.sdk.language.SimpleFoldingBuilder"/>
<gotoSymbolContributor implementation="com.intellij.sdk.language.SimpleChooseByNameContributor"/>
<lang.psiStructureViewFactory language="Simple" implementationClass="com.intellij.sdk.language.SimpleStructureViewFactory"/>
<lang.formatter language="Simple" implementationClass="com.intellij.sdk.language.SimpleFormattingModelBuilder"/>
<codeStyleSettingsProvider implementation="com.intellij.sdk.language.SimpleCodeStyleSettingsProvider"/>
<langCodeStyleSettingsProvider implementation="com.intellij.sdk.language.SimpleLanguageCodeStyleSettingsProvider"/>
<lang.commenter language="Simple" implementationClass="com.intellij.sdk.language.SimpleCommenter"/>
</extensions>
</idea-plugin>

View File

@ -0,0 +1,58 @@
<svg xmlns="http://www.w3.org/2000/svg" width="81" height="80" viewBox="0 0 81 80">
<defs>
<linearGradient id="pluginsdk_80-a" x1="-.031%" x2="100.053%" y1="49.963%" y2="49.963%">
<stop offset="25.81%" stop-color="#F97A12"/>
<stop offset="45.91%" stop-color="#B07B58"/>
<stop offset="72.41%" stop-color="#577BAE"/>
<stop offset="91.05%" stop-color="#1E7CE5"/>
<stop offset="100%" stop-color="#087CFA"/>
</linearGradient>
<linearGradient id="pluginsdk_80-b" x1="27.55%" x2="82.223%" y1="34.514%" y2="77.605%">
<stop offset="0%" stop-color="#F97A12"/>
<stop offset="7.18%" stop-color="#CB7A3E"/>
<stop offset="15.41%" stop-color="#9E7B6A"/>
<stop offset="24.2%" stop-color="#757B91"/>
<stop offset="33.44%" stop-color="#537BB1"/>
<stop offset="43.24%" stop-color="#387CCC"/>
<stop offset="53.81%" stop-color="#237CE0"/>
<stop offset="65.52%" stop-color="#147CEF"/>
<stop offset="79.25%" stop-color="#0B7CF7"/>
<stop offset="100%" stop-color="#087CFA"/>
</linearGradient>
<linearGradient id="pluginsdk_80-c" x1="63.121%" x2="40.793%" y1="97.699%" y2="-6.587%">
<stop offset="0%" stop-color="#FE315D"/>
<stop offset="7.84%" stop-color="#CB417E"/>
<stop offset="16.01%" stop-color="#9E4E9B"/>
<stop offset="24.74%" stop-color="#755BB4"/>
<stop offset="33.92%" stop-color="#5365CA"/>
<stop offset="43.65%" stop-color="#386DDB"/>
<stop offset="54.14%" stop-color="#2374E9"/>
<stop offset="65.76%" stop-color="#1478F3"/>
<stop offset="79.4%" stop-color="#0B7BF8"/>
<stop offset="100%" stop-color="#087CFA"/>
</linearGradient>
<linearGradient id="pluginsdk_80-d" x1="25.331%" x2="93.854%" y1="24.119%" y2="132.621%">
<stop offset="0%" stop-color="#FE315D"/>
<stop offset="4.023%" stop-color="#F63462"/>
<stop offset="10.37%" stop-color="#DF3A71"/>
<stop offset="16.67%" stop-color="#C24383"/>
<stop offset="29.12%" stop-color="#AD4A91"/>
<stop offset="54.98%" stop-color="#755BB4"/>
<stop offset="91.75%" stop-color="#1D76ED"/>
<stop offset="100%" stop-color="#087CFA"/>
</linearGradient>
</defs>
<g fill="none" fill-rule="evenodd">
<g fill-rule="nonzero" transform="translate(8 8)">
<path fill="url(#pluginsdk_80-a)" d="M6.08754566,64 L2.66453526e-15,59.1000946 L0,26.7918961 L30,38.6703369 L10.1403967,64 L6.08754566,64 Z"/>
<path fill="url(#pluginsdk_80-b)" d="M20.9524706,64 L52.2740919,31.9159091 L37.6708832,0.460194805 L38.0580944,1.33226763e-15 L64,0 L64,64 L20.9524706,64 Z"/>
<path fill="url(#pluginsdk_80-c)" d="M34.4123783,0 L64,0 L64,28.0366227 L49.0078336,44 L34,0.44696173 L34.4123783,0 Z"/>
<path fill="url(#pluginsdk_80-d)" d="M30.3358775,64 L0,64 L0,49.9709549 L6.23437817,29.2830519 L0,27.1596093 L0,0 L39.4697238,0 L58,21.3844805 L30.5381317,63.9259091 L30.3358775,64 Z"/>
</g>
<g fill-rule="nonzero" transform="translate(12 12)">
<rect width="56" height="56" fill="#000"/>
<rect width="22" height="4" x="4" y="46" fill="#FFFEFE"/>
<path fill="#FFFEFE" d="M11.128,25.28 C8.584,25.28 6.016,24.392 4,22.592 L6.184,19.976 C7.696,21.224 9.28,22.016 11.2,22.016 C12.712,22.016 13.624,21.416 13.624,20.432 L13.624,20.384 C13.624,19.448 13.048,18.968 10.24,18.248 C6.856,17.384 4.672,16.448 4.672,13.112 L4.672,13.064 C4.672,10.016 7.12,8 10.552,8 C13,8 15.088,8.768 16.792,10.136 L14.872,12.92 C13.384,11.888 11.92,11.264 10.504,11.264 C9.088,11.264 8.344,11.912 8.344,12.728 L8.344,12.776 C8.344,13.88 9.064,14.24 11.968,14.984 C15.376,15.872 17.296,17.096 17.296,20.024 L17.296,20.072 C17.296,23.408 14.752,25.28 11.128,25.28 Z M19.512,25.04 L19.512,8.24 L26.064,8.24 C31.344,8.24 34.992,11.864 34.992,16.592 L34.992,16.64 C34.992,21.368 31.344,25.04 26.064,25.04 L19.512,25.04 Z M26.064,11.576 L23.208,11.576 L23.208,21.704 L26.064,21.704 C29.088,21.704 31.128,19.664 31.128,16.688 L31.128,16.64 C31.128,13.664 29.088,11.576 26.064,11.576 Z M37.28,25.04 L37.28,8.24 L40.976,8.24 L40.976,15.584 L47.744,8.24 L52.28,8.24 L45.416,15.368 L52.568,25.04 L48.128,25.04 L42.92,17.888 L40.976,19.904 L40.976,25.04 L37.28,25.04 Z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

View File

@ -0,0 +1,83 @@
package com.intellij.sdk.language;
import com.intellij.application.options.CodeStyle;
import com.intellij.codeInsight.completion.CompletionType;
import com.intellij.codeInsight.generation.actions.CommentByLineCommentAction;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
import com.intellij.usageView.UsageInfo;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.sdk.language.psi.SimpleProperty;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public class SimpleCodeInsightTest extends LightJavaCodeInsightFixtureTestCase {
/**
*
* @return path to test data file directory relative to working directory in the run configuration for this test.
*/
@Override
protected String getTestDataPath() {
return "src/test/testData";
}
public void testCompletion() {
myFixture.configureByFiles("CompleteTestData.java", "DefaultTestData.simple");
myFixture.complete(CompletionType.BASIC, 1);
List<String> strings = myFixture.getLookupElementStrings();
assertTrue(strings.containsAll(Arrays.asList("key with spaces", "language", "message", "tab", "website")));
assertEquals(5, strings.size());
}
public void testAnnotator() {
myFixture.configureByFiles("AnnotatorTestData.java", "DefaultTestData.simple");
myFixture.checkHighlighting(false, false, true, true);
}
public void testFormatter() {
myFixture.configureByFiles("FormatterTestData.simple");
CodeStyle.getLanguageSettings(myFixture.getFile()).SPACE_AROUND_ASSIGNMENT_OPERATORS = true;
CodeStyle.getLanguageSettings(myFixture.getFile()).KEEP_BLANK_LINES_IN_CODE = 2;
WriteCommandAction.writeCommandAction(getProject()).run(() -> {
CodeStyleManager.getInstance(getProject()).reformatText(myFixture.getFile(),
ContainerUtil.newArrayList(myFixture.getFile().getTextRange()));
});
myFixture.checkResultByFile("DefaultTestData.simple");
}
public void testRename() {
myFixture.configureByFiles("RenameTestData.java", "RenameTestData.simple");
myFixture.renameElementAtCaret("websiteUrl");
myFixture.checkResultByFile("RenameTestData.simple", "RenameTestDataAfter.simple", false);
}
public void testFolding() {
myFixture.configureByFiles("DefaultTestData.simple");
myFixture.testFolding(getTestDataPath() + "/FoldingTestData.java");
}
public void testFindUsages() {
Collection<UsageInfo> usageInfos = myFixture.testFindUsages("FindUsagesTestData.simple", "FindUsagesTestData.java");
assertEquals(1, usageInfos.size());
}
public void testCommenter() {
myFixture.configureByText(SimpleFileType.INSTANCE, "<caret>website = http://en.wikipedia.org/");
CommentByLineCommentAction commentAction = new CommentByLineCommentAction();
commentAction.actionPerformedImpl(getProject(), myFixture.getEditor());
myFixture.checkResult("#website = http://en.wikipedia.org/");
commentAction.actionPerformedImpl(getProject(), myFixture.getEditor());
myFixture.checkResult("website = http://en.wikipedia.org/");
}
public void testReference() {
myFixture.configureByFiles("ReferenceTestData.java", "DefaultTestData.simple");
PsiElement element = myFixture.getFile().findElementAt(myFixture.getCaretOffset()).getParent();
assertEquals("http://en.wikipedia.org/", ((SimpleProperty) element.getReferences()[0].resolve()).getValue());
}
}

View File

@ -0,0 +1,32 @@
package com.intellij.sdk.language;
import com.intellij.testFramework.ParsingTestCase;
public class SimpleParsingTest extends ParsingTestCase {
public SimpleParsingTest() {
super("", "simple", new SimpleParserDefinition());
}
public void testParsingTestData() {
doTest(true);
}
/**
*
* @return path to test data file directory relative to root of this module.
*/
@Override
protected String getTestDataPath() {
return "src/test/testData";
}
@Override
protected boolean skipSpaces() {
return false;
}
@Override
protected boolean includeRanges() {
return true;
}
}

View File

@ -0,0 +1,7 @@
public class Test {
public static void main(String[] args) {
System.out.println("simple:website");
System.out.println("simple:key with spaces");
System.out.println("simple:<error descr="Unresolved property">websit</error>");
}
}

View File

@ -0,0 +1,5 @@
public class Test {
public static void main(String[] args) {
System.out.println("simple:<caret>");
}
}

View File

@ -0,0 +1,14 @@
# You are reading the ".properties" entry.
! The exclamation mark can also mark text as comments.
website = http://en.wikipedia.org/
language = English
# The backslash below tells the application to continue reading
# the value onto the next line.
message = Welcome to \
Wikipedia!
# Add spaces to the key
key\ with\ spaces = This is the value that could be looked up with the key "key with spaces".
# Unicode
tab : \u0009

View File

@ -0,0 +1,5 @@
public class Test {
public static void main(String[] args) {
System.out.println("simple:key with spaces");
}
}

View File

@ -0,0 +1,13 @@
# You are reading the ".properties" entry.
! The exclamation mark can also mark text as comments.
website = http://en.wikipedia.org/
language = English
# The backslash below tells the application to continue reading
# the value onto the next line.
message = Welcome to \
Wikipedia!
# Add spaces to the key
<caret>key\ with\ spaces = This is the value that could be looked up with the key "key with spaces".
# Unicode
tab : \u0009

View File

@ -0,0 +1,11 @@
public class Test {
public static void main(String[] args)<fold text=' { '> {
</fold>System.out.println("<fold text='http://en.wikipedia.org/'>simple:website</fold>");<fold text=' }'>
}</fold>
public static void main1(String[] args)<fold text=' { '> {
</fold>System.out.println("<fold text='This is the value that could be looked up with the key \"key with spaces\".'>simple:key with spaces</fold>");<fold text=' }'>
}</fold>
public static void main2(String[] args)<fold text=' { '> {
</fold>System.out.println("<fold text='Welcome to \n Wikipedia!'>simple:message</fold>");<fold text=' }'>
}</fold>
}

View File

@ -0,0 +1,15 @@
# You are reading the ".properties" entry.
! The exclamation mark can also mark text as comments.
website=http://en.wikipedia.org/
language= English
# The backslash below tells the application to continue reading
# the value onto the next line.
message = Welcome to \
Wikipedia!
# Add spaces to the key
key\ with\ spaces = This is the value that could be looked up with the key "key with spaces".
# Unicode
tab :\u0009

View File

@ -0,0 +1,17 @@
# You are reading the ".properties" entry.
! The exclamation mark can also mark text as comments.
website = http://en.wikipedia.org/
language = English
# The backslash below tells the application to continue reading
# the value onto the next line.
message = Welcome to \
Wikipedia!
# Add spaces to the key
key\ with\ spaces = This is the value that could be looked up with the key "key with spaces".
# Unicode
tab : \u0009
# test for illegal key attempt
key\
with\
endofline = test

View File

@ -0,0 +1,66 @@
Simple File(0,492)
PsiComment(SimpleTokenType.COMMENT)('# You are reading the ".properties" entry.')(0,42)
PsiWhiteSpace('\n')(42,43)
PsiComment(SimpleTokenType.COMMENT)('! The exclamation mark can also mark text as comments.')(43,97)
PsiWhiteSpace('\n')(97,98)
SimplePropertyImpl(PROPERTY)(98,132)
PsiElement(SimpleTokenType.KEY)('website')(98,105)
PsiWhiteSpace(' ')(105,106)
PsiElement(SimpleTokenType.SEPARATOR)('=')(106,107)
PsiWhiteSpace(' ')(107,108)
PsiElement(SimpleTokenType.VALUE)('http://en.wikipedia.org/')(108,132)
PsiWhiteSpace('\n\n')(132,134)
SimplePropertyImpl(PROPERTY)(134,152)
PsiElement(SimpleTokenType.KEY)('language')(134,142)
PsiWhiteSpace(' ')(142,143)
PsiElement(SimpleTokenType.SEPARATOR)('=')(143,144)
PsiWhiteSpace(' ')(144,145)
PsiElement(SimpleTokenType.VALUE)('English')(145,152)
PsiWhiteSpace('\n')(152,153)
PsiComment(SimpleTokenType.COMMENT)('# The backslash below tells the application to continue reading')(153,216)
PsiWhiteSpace('\n')(216,217)
PsiComment(SimpleTokenType.COMMENT)('# the value onto the next line.')(217,248)
PsiWhiteSpace('\n')(248,249)
SimplePropertyImpl(PROPERTY)(249,292)
PsiElement(SimpleTokenType.KEY)('message')(249,256)
PsiWhiteSpace(' ')(256,257)
PsiElement(SimpleTokenType.SEPARATOR)('=')(257,258)
PsiWhiteSpace(' ')(258,259)
PsiElement(SimpleTokenType.VALUE)('Welcome to \\n Wikipedia!')(259,292)
PsiWhiteSpace('\n')(292,293)
PsiComment(SimpleTokenType.COMMENT)('# Add spaces to the key')(293,316)
PsiWhiteSpace('\n')(316,317)
SimplePropertyImpl(PROPERTY)(317,410)
PsiElement(SimpleTokenType.KEY)('key\ with\ spaces')(317,334)
PsiWhiteSpace(' ')(334,335)
PsiElement(SimpleTokenType.SEPARATOR)('=')(335,336)
PsiWhiteSpace(' ')(336,337)
PsiElement(SimpleTokenType.VALUE)('This is the value that could be looked up with the key "key with spaces".')(337,410)
PsiWhiteSpace('\n')(410,411)
PsiComment(SimpleTokenType.COMMENT)('# Unicode')(411,420)
PsiWhiteSpace('\n')(420,421)
SimplePropertyImpl(PROPERTY)(421,433)
PsiElement(SimpleTokenType.KEY)('tab')(421,424)
PsiWhiteSpace(' ')(424,425)
PsiElement(SimpleTokenType.SEPARATOR)(':')(425,426)
PsiWhiteSpace(' ')(426,427)
PsiElement(SimpleTokenType.VALUE)('\u0009')(427,433)
PsiWhiteSpace('\n')(433,434)
PsiComment(SimpleTokenType.COMMENT)('# test for illegal key attempt')(434,464)
PsiWhiteSpace('\n')(464,465)
SimplePropertyImpl(PROPERTY)(465,469)
PsiElement(SimpleTokenType.KEY)('key')(465,468)
PsiErrorElement:SimpleTokenType.SEPARATOR expected, got '\'(468,469)
PsiElement(BAD_CHARACTER)('\')(468,469)
PsiWhiteSpace('\n')(469,470)
SimplePropertyImpl(PROPERTY)(470,475)
PsiElement(SimpleTokenType.KEY)('with')(470,474)
PsiErrorElement:SimpleTokenType.SEPARATOR expected, got '\'(474,475)
PsiElement(BAD_CHARACTER)('\')(474,475)
PsiWhiteSpace('\n')(475,476)
SimplePropertyImpl(PROPERTY)(476,492)
PsiElement(SimpleTokenType.KEY)('endofline')(476,485)
PsiWhiteSpace(' ')(485,486)
PsiElement(SimpleTokenType.SEPARATOR)('=')(486,487)
PsiWhiteSpace(' ')(487,488)
PsiElement(SimpleTokenType.VALUE)('test')(488,492)

View File

@ -0,0 +1,5 @@
public class Test {
public static void main(String[] args) {
System.out.println("simple:website<caret>");
}
}

View File

@ -0,0 +1,5 @@
public class Test {
public static void main(String[] args) {
System.out.println("simple:website<caret>");
}
}

View File

@ -0,0 +1,13 @@
# You are reading the ".properties" entry.
! The exclamation mark can also mark text as comments.
website = http://en.wikipedia.org/
language = English
# The backslash below tells the application to continue reading
# the value onto the next line.
message = Welcome to \
Wikipedia!
# Add spaces to the key
key\ with\ spaces = This is the value that could be looked up with the key "key with spaces".
# Unicode
tab : \u0009

View File

@ -0,0 +1,13 @@
# You are reading the ".properties" entry.
! The exclamation mark can also mark text as comments.
websiteUrl = http://en.wikipedia.org/
language = English
# The backslash below tells the application to continue reading
# the value onto the next line.
message = Welcome to \
Wikipedia!
# Add spaces to the key
key\ with\ spaces = This is the value that could be looked up with the key "key with spaces".
# Unicode
tab : \u0009

View File

@ -3,6 +3,7 @@ package com.simpleplugin;
import com.intellij.lang.ASTNode;
import com.intellij.lang.folding.*;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
@ -12,7 +13,7 @@ import org.jetbrains.annotations.*;
import java.util.*;
public class SimpleFoldingBuilder extends FoldingBuilderEx {
public class SimpleFoldingBuilder extends FoldingBuilderEx implements DumbAware {
@NotNull
@Override
public FoldingDescriptor[] buildFoldRegions(@NotNull PsiElement root, @NotNull Document document, boolean quick) {
@ -52,7 +53,18 @@ public class SimpleFoldingBuilder extends FoldingBuilderEx {
@Nullable
@Override
public String getPlaceholderText(@NotNull ASTNode node) {
return "...";
String retTxt = "...";
if ( node.getPsi() instanceof PsiLiteralExpression ) {
PsiLiteralExpression nodeElement = (PsiLiteralExpression) node.getPsi();
String key = ((String) nodeElement.getValue()).substring("simple:".length());
final List< SimpleProperty > properties = SimpleUtil.findProperties(nodeElement.getProject(), key);
String place = properties.get(0).getValue();
// IMPORTANT: keys can come with no values, so a test for null is needed
// IMPORTANT: Convert embedded \n to backslash n, so that the string will look
// like it has LF embedded in it and embedded " to escaped "
return place == null ? retTxt : place.replaceAll("\n", "\\n").replaceAll("\"", "\\\\\"");
}
return retTxt;
}
@Override

View File

@ -27,19 +27,16 @@ public class SimpleParserDefinition implements ParserDefinition {
}
@NotNull
@Override
public TokenSet getCommentTokens() {
return COMMENTS;
}
@NotNull
@Override
public TokenSet getStringLiteralElements() {
return TokenSet.EMPTY;
}
@NotNull
@Override
public PsiParser createParser(final Project project) {
return new SimpleParser();
}
@ -49,19 +46,16 @@ public class SimpleParserDefinition implements ParserDefinition {
return FILE;
}
@Override
public PsiFile createFile(FileViewProvider viewProvider) {
return new SimpleFile(viewProvider);
}
@Override
public SpaceRequirements spaceExistenceTypeBetweenTokens(ASTNode left, ASTNode right) {
return SpaceRequirements.MAY;
}
@NotNull
@Override
public PsiElement createElement(ASTNode node) {
return SimpleTypes.Factory.createElement(node);
}
}
}

View File

@ -2,6 +2,6 @@ public class Test {
public static void main(String[] args) {
System.out.println("simple:website");
System.out.println("simple:key with spaces");
System.out.println("simple:<error descr="Unresolved property">websit"</error>);
System.out.println("simple:<error descr="Unresolved property">websit</error>");
}
}

View File

@ -6,7 +6,7 @@ import com.intellij.codeInsight.generation.actions.CommentByLineCommentAction;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
import com.intellij.usageView.UsageInfo;
import com.intellij.util.containers.ContainerUtil;
import com.simpleplugin.psi.SimpleProperty;
@ -15,12 +15,13 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public class SimpleCodeInsightTest extends LightCodeInsightFixtureTestCase {
public class SimpleCodeInsightTest extends LightJavaCodeInsightFixtureTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
}
// path to test data file directory relative to working directory in the run configuration for this test.
@Override
protected String getTestDataPath() { return "testData"; }