Various improvements;

Started with support for formatting (under construction);
This commit is contained in:
Rik 2014-07-08 11:28:25 +02:00
parent e855b5507e
commit 9ce4d08f80
20 changed files with 1153 additions and 512 deletions

View File

@ -1,6 +1,6 @@
<idea-plugin version="2">
<id>com.powertuple.intellij.haskell</id>
<name>Haskell plugin for IntelliJ</name>
<name>Haskell</name>
<version>0.1</version>
<vendor email="rikvdkleij@gmail.com" url="http://www.powertuple.com">PowerTuple</vendor>
@ -39,6 +39,10 @@
<applicationConfigurable instance="com.powertuple.intellij.haskell.settings.HaskellConfigurable"/>
<applicationService serviceImplementation="com.powertuple.intellij.haskell.settings.HaskellSettings"/>
<lang.formatter language="Haskell" implementationClass="com.powertuple.intellij.haskell.formatter.HaskellFormattingModelBuilder"/>
<codeStyleSettingsProvider implementation="com.powertuple.intellij.haskell.formatter.settings.HaskellCodeStyleSettingsProvider"/>
<langCodeStyleSettingsProvider implementation="com.powertuple.intellij.haskell.formatter.settings.HaskellLanguageCodeStyleSettingsProvider"/>
</extensions>
<application-components>

View File

@ -14,7 +14,7 @@ Other Haskell support by help from external tools as ghc-mod(i).
In the meantime also Atsky started to create [Haskell-idea-plugin](https://github.com/Atsky/haskell-idea-plugin) based on ideah plugin in Kotlin. First I saw clear difference
in approach (besides language) but it looks like we are eventually using to same approach to support Haskell code in IntelliJ.
This plugin is written in Java/Scala and is mentioned not to support GHC/Cabal directly. Mine idea is to support sandbox projects
This plugin is written in Java/Scala and is mentioned not to support GHC/Cabal directly. My idea is to support sandbox projects
and doing the initial/basic Haskell configuration in terminal. This plugin will rely on external tools (mainly ghc-mod(i)) for Haskell language support in IntelliJ IDEA.
The code in this project for setting the paths to external tools is based on Haskell-idea-plugin. I have no experience in creating IntelliJ
plugins so it's 'inspiring' to look to code of other plugins :-)

View File

@ -0,0 +1,29 @@
/*
* Copyright 2014 Rik van der Kleij
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.powertuple.intellij.haskell
import com.intellij.notification.NotificationGroup
import com.intellij.openapi.ui.MessageType
object HaskellNotificationGroup {
private val Group = NotificationGroup.balloonGroup("Haskell")
def notifyError(message: String) {
Group.createNotification(message, MessageType.ERROR).notify(null)
}
}

View File

@ -33,10 +33,25 @@ import com.powertuple.intellij.haskell.psi.HaskellFile;
import com.powertuple.intellij.haskell.psi.HaskellTypes;
import org.jetbrains.annotations.NotNull;
import static com.powertuple.intellij.haskell.psi.HaskellTypes.*;
public class HaskellParserDefinition implements ParserDefinition {
public static final TokenSet WHITE_SPACES = TokenSet.create(TokenType.WHITE_SPACE);
public static final TokenSet COMMENTS = TokenSet.create(HaskellTypes.HS_COMMENT, HaskellTypes.HS_NCOMMENT);
public static final TokenSet RESERVED_IDS = TokenSet.create(
HS_CASE, HS_CLASS, HS_DATA, HS_DEFAULT, HS_DERIVING, HS_DO, HS_ELSE, HS_FOREIGN,
HS_IF, HS_IMPORT, HS_IN, HS_INFIX, HS_INFIXL, HS_INFIXR, HS_INSTANCE, HS_LET,
HS_MODULE, HS_NEWTYPE, HS_OF, HS_THEN, HS_TYPE, HS_WHERE, HS_UNDERSCORE,
HS_AS, HS_QUALIFIED, HS_HIDING
);
public static final TokenSet OPERATORS = TokenSet.create(
HS_DOT_DOT, HS_COLON, HS_COLON_COLON, HS_DEFINED_BY, HS_SLASH, HS_VERTICAL_BAR,
HS_LEFT_ARROW, HS_RIGHT_ARROW, HS_AT, HS_TILDE, HS_DOUBLE_RIGHT_ARROW,
HS_QVARSYM, HS_VARSYM, HS_QCONSYM, HS_CONSYM
);
@NotNull
@Override
public Lexer createLexer(Project project) {
@ -89,4 +104,4 @@ public class HaskellParserDefinition implements ParserDefinition {
public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode left, ASTNode right) {
return SpaceRequirements.MAY;
}
}
}

View File

@ -18,9 +18,9 @@ import static com.powertuple.intellij.haskell.psi.HaskellTypes.*;
%type IElementType
%unicode
control_character = [\000 - \037]
newline = \r|\n|\r\n|\f
WHITECHAR = ({newline} | ' ' | \t | {control_character} | \ )
control_character = [\000 - \037]
NEWLINE = \r|\n|\r\n
WHITE_SPACE = ([ \t\f] | {control_character})+
small = [a-z_] // ignoring any unicode lowercase letter for now
large = [A-Z] // ignoring any unicode uppercase letter for now
@ -36,7 +36,7 @@ OCTAL = 0[oO]{octit}+
FLOAT = [-+]?([0-9]+(\\.[0-9]*)?|\\.[0-9]+)([eE][-+]?[0-9]+)?
COMMENT = "--"[^\r\n]*
NCOMMENT = "{-" (.|{newline})* "-}"
NCOMMENT = "{-" (.|{NEWLINE})* "-}"
CHARACTER_LITERAL = \' [^\'\\\r\n\f]* \'
STRING_LITERAL = \" [^\"\\\r\n\f]* \"
@ -47,10 +47,44 @@ CON_ID = {large} ({small} | {large})*
%%
<YYINITIAL> {
{WHITECHAR} { return HS_WHITE_CHAR;}
{COMMENT} { return HS_COMMENT; }
{NCOMMENT} { return HS_NCOMMENT; }
{NEWLINE} { return HS_NEWLINE; }
{WHITE_SPACE} { return com.intellij.psi.TokenType.WHITE_SPACE; }
// not listed as reserved identifier but have meaning in certain context,
// let's say specialreservedid
"as" { return HS_AS; }
"qualified" { return HS_QUALIFIED; }
"hiding" { return HS_HIDING; }
// reservedid
"case" { return HS_CASE; }
"class" { return HS_CLASS; }
"data" { return HS_DATA; }
"default" { return HS_DEFAULT; }
"deriving" { return HS_DERIVING; }
"do" { return HS_DO; }
"else" { return HS_ELSE; }
"foreign" { return HS_FOREIGN; }
"if" { return HS_IF; }
"import" { return HS_IMPORT; }
"in" { return HS_IN; }
"infix" { return HS_INFIX; }
"infixl" { return HS_INFIXL; }
"infixr" { return HS_INFIXR; }
"instance" { return HS_INSTANCE; }
"let" { return HS_LET; }
"module" { return HS_MODULE; }
"newtype" { return HS_NEWTYPE; }
"of" { return HS_OF; }
"then" { return HS_THEN; }
"type" { return HS_TYPE; }
"where" { return HS_WHERE; }
"_" { return HS_UNDERSCORE; }
{VAR_ID} { return HS_VAR_ID; }
{CON_ID} { return HS_CON_ID; }
{CHARACTER_LITERAL} { return HS_CHARACTER_LITERAL; }
{STRING_LITERAL} { return HS_STRING_LITERAL; }
@ -91,7 +125,7 @@ CON_ID = {large} ({small} | {large})*
".." { return HS_DOT_DOT; }
"::" { return HS_COLON_COLON; }
":" { return HS_COLON; }
"=" { return HS_DEFINED_BY; }
"=" { return HS_EQUAL; }
"\\" { return HS_BACKSLASH; }
"|" { return HS_VERTICAL_BAR; }
"<-" { return HS_LEFT_ARROW; }
@ -100,39 +134,5 @@ CON_ID = {large} ({small} | {large})*
"~" { return HS_TILDE; }
"=>" { return HS_DOUBLE_RIGHT_ARROW; }
// not listed as reserved identifier but have meaning in certain context,
// let's say specialreservedid
"as" { return HS_AS; }
"qualified" { return HS_QUALIFIED; }
"hiding" { return HS_HIDING; }
// reservedid
"case" { return HS_CASE; }
"class" { return HS_CLASS; }
"data" { return HS_DATA; }
"default" { return HS_DEFAULT; }
"deriving" { return HS_DERIVING; }
"do" { return HS_DO; }
"else" { return HS_ELSE; }
"foreign" { return HS_FOREIGN; }
"if" { return HS_IF; }
"import" { return HS_IMPORT; }
"in" { return HS_IN; }
"infix" { return HS_INFIX; }
"infixl" { return HS_INFIXL; }
"infixr" { return HS_INFIXR; }
"instance" { return HS_INSTANCE; }
"let" { return HS_LET; }
"module" { return HS_MODULE; }
"newtype" { return HS_NEWTYPE; }
"of" { return HS_OF; }
"then" { return HS_THEN; }
"type" { return HS_TYPE; }
"where" { return HS_WHERE; }
"_" { return HS_UNDERSCORE; }
{VAR_ID} { return HS_VAR_ID; }
{CON_ID} { return HS_CON_ID; }
[^] { return com.intellij.psi.TokenType.BAD_CHARACTER; }
. { return com.intellij.psi.TokenType.BAD_CHARACTER; }
}

View File

@ -1,4 +1,4 @@
/* The following code was generated by JFlex 1.4.3 on 6/24/14 5:41 PM */
/* The following code was generated by JFlex 1.4.3 on 7/4/14 11:04 AM */
package com.powertuple.intellij.haskell;
import com.intellij.lexer.*;
@ -9,7 +9,7 @@ import static com.powertuple.intellij.haskell.psi.HaskellTypes.*;
/**
* This class is a scanner generated by
* <a href="http://www.jflex.de/">JFlex</a> 1.4.3
* on 6/24/14 5:41 PM from the specification file
* on 7/4/14 11:04 AM from the specification file
* <tt>/home/rik/idea/intellij-haskell/src/com/powertuple/intellij/haskell/_HaskellLexer.flex</tt>
*/
public class _HaskellLexer implements FlexLexer {
@ -33,14 +33,14 @@ public class _HaskellLexer implements FlexLexer {
* Translates characters to character classes
*/
private static final String ZZ_CMAP_PACKED =
"\1\1\10\0\1\1\1\3\1\0\1\4\1\2\21\0\1\1\1\1"+
"\1\31\1\30\1\32\1\33\1\34\1\35\1\5\1\45\1\46\1\36"+
"\1\21\1\47\1\25\1\37\1\40\1\13\7\16\2\10\1\54\1\50"+
"\1\41\1\55\1\42\1\43\1\57\4\12\1\24\1\12\10\7\1\20"+
"\10\7\1\15\2\7\1\51\1\22\1\52\1\44\1\104\1\53\1\61"+
"\1\11\1\74\1\70\1\23\1\67\1\73\1\71\1\66\2\6\1\65"+
"\1\100\1\72\1\17\1\101\1\63\1\76\1\62\1\75\1\64\1\77"+
"\1\102\1\14\1\103\1\6\1\26\1\56\1\27\1\60\uff81\0";
"\1\1\10\0\1\1\1\3\1\0\1\27\1\2\21\0\1\1\1\1"+
"\1\55\1\30\1\56\1\57\1\60\1\61\1\26\1\71\1\72\1\62"+
"\1\17\1\73\1\23\1\63\1\64\1\11\7\14\2\6\1\100\1\74"+
"\1\65\1\101\1\66\1\67\1\103\4\10\1\22\1\10\10\5\1\16"+
"\10\5\1\13\2\5\1\75\1\20\1\76\1\70\1\54\1\77\1\31"+
"\1\7\1\44\1\40\1\21\1\37\1\43\1\41\1\36\2\4\1\35"+
"\1\50\1\42\1\15\1\51\1\33\1\46\1\32\1\45\1\34\1\47"+
"\1\52\1\12\1\53\1\4\1\24\1\102\1\25\1\104\uff81\0";
/**
* Translates characters to character classes
@ -53,22 +53,22 @@ public class _HaskellLexer implements FlexLexer {
private static final int [] ZZ_ACTION = zzUnpackAction();
private static final String ZZ_ACTION_PACKED_0 =
"\1\0\1\1\2\2\1\1\1\3\1\4\2\5\1\3"+
"\1\6\1\7\1\3\1\10\1\11\1\12\1\1\1\13"+
"\1\0\1\1\1\2\2\3\1\4\1\5\2\6\1\4"+
"\1\7\1\10\1\4\1\11\1\12\1\13\2\1\14\4"+
"\1\14\1\15\1\16\1\17\1\20\1\21\1\22\1\23"+
"\1\24\1\25\1\26\1\27\1\30\1\31\1\32\1\33"+
"\1\34\1\35\1\36\1\37\1\40\1\41\1\42\14\3"+
"\1\43\5\0\1\44\1\45\2\0\1\3\1\46\1\47"+
"\2\0\1\50\1\51\1\52\1\53\1\54\1\55\2\3"+
"\1\56\1\57\2\3\1\60\12\3\1\61\2\45\1\0"+
"\1\62\1\63\1\3\1\0\1\3\1\64\17\3\1\65"+
"\1\66\7\3\1\67\2\3\1\70\1\3\1\71\1\72"+
"\4\3\1\73\6\3\1\74\1\3\1\75\2\3\1\76"+
"\1\77\1\100\3\3\1\101\1\3\1\102\2\3\1\103"+
"\1\104\1\3\1\105\1\3\1\106\1\107\1\110";
"\1\34\1\35\1\36\1\37\1\40\1\41\1\42\1\43"+
"\1\44\4\0\1\45\1\46\2\0\1\4\1\47\1\50"+
"\2\0\1\51\1\0\1\52\1\53\2\4\1\54\1\55"+
"\2\4\1\56\12\4\1\57\1\60\1\61\1\62\2\46"+
"\1\0\1\63\1\64\1\4\1\0\1\4\1\65\17\4"+
"\1\66\1\67\7\4\1\70\2\4\1\71\1\4\1\72"+
"\1\73\4\4\1\74\6\4\1\75\1\4\1\76\2\4"+
"\1\77\1\100\1\101\3\4\1\102\1\4\1\103\2\4"+
"\1\104\1\105\1\4\1\106\1\4\1\107\1\110\1\111";
private static int [] zzUnpackAction() {
int [] result = new int[167];
int [] result = new int[168];
int offset = 0;
offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
return result;
@ -93,30 +93,30 @@ public class _HaskellLexer implements FlexLexer {
private static final int [] ZZ_ROWMAP = zzUnpackRowMap();
private static final String ZZ_ROWMAP_PACKED_0 =
"\0\0\0\105\0\105\0\212\0\317\0\u0114\0\u0159\0\u019e"+
"\0\0\0\105\0\212\0\317\0\105\0\u0114\0\u0159\0\u019e"+
"\0\u01e3\0\u0228\0\u026d\0\u02b2\0\u02f7\0\u033c\0\u0381\0\105"+
"\0\u03c6\0\105\0\105\0\105\0\105\0\105\0\105\0\u040b"+
"\0\105\0\u0450\0\105\0\105\0\105\0\105\0\105\0\105"+
"\0\105\0\105\0\105\0\105\0\u0495\0\u04da\0\105\0\105"+
"\0\105\0\u051f\0\u0564\0\u05a9\0\u05ee\0\u0633\0\u0678\0\u06bd"+
"\0\u0702\0\u0747\0\u078c\0\u07d1\0\u0816\0\u0114\0\u085b\0\u08a0"+
"\0\u03c6\0\u040b\0\u0450\0\u0495\0\u04da\0\u051f\0\u0564\0\u05a9"+
"\0\u05ee\0\u0633\0\u0678\0\u06bd\0\u0702\0\u0747\0\u0114\0\105"+
"\0\105\0\105\0\105\0\105\0\105\0\u078c\0\105\0\u07d1"+
"\0\105\0\105\0\105\0\105\0\105\0\105\0\105\0\105"+
"\0\105\0\105\0\u0816\0\u085b\0\105\0\105\0\105\0\u08a0"+
"\0\u08e5\0\u092a\0\u096f\0\u0114\0\u09b4\0\u02b2\0\u09f9\0\u0a3e"+
"\0\u0a83\0\105\0\u0ac8\0\u03c6\0\105\0\105\0\105\0\105"+
"\0\105\0\u0114\0\u0b0d\0\u0b52\0\u0114\0\u0b97\0\u0bdc\0\u0c21"+
"\0\u0114\0\u0c66\0\u0cab\0\u0cf0\0\u0d35\0\u0d7a\0\u0dbf\0\u0e04"+
"\0\u0e49\0\u0e8e\0\u0ed3\0\105\0\u0f18\0\u0f5d\0\u0f5d\0\u092a"+
"\0\u096f\0\u0fa2\0\u0fe7\0\u102c\0\u0114\0\u1071\0\u10b6\0\u10fb"+
"\0\u1140\0\u1185\0\u11ca\0\u120f\0\u1254\0\u1299\0\u12de\0\u1323"+
"\0\u1368\0\u13ad\0\u13f2\0\u1437\0\u0114\0\u0ac8\0\u147c\0\u14c1"+
"\0\u1506\0\u154b\0\u1590\0\u15d5\0\u161a\0\u0114\0\u165f\0\u16a4"+
"\0\u0114\0\u16e9\0\u0114\0\u0114\0\u172e\0\u1773\0\u17b8\0\u17fd"+
"\0\u1842\0\u1887\0\u18cc\0\u1911\0\u1956\0\u199b\0\u19e0\0\u0114"+
"\0\u1a25\0\u0114\0\u1a6a\0\u1aaf\0\u0114\0\u0114\0\u0114\0\u1af4"+
"\0\u1b39\0\u1b7e\0\u0114\0\u1bc3\0\u0114\0\u1c08\0\u1c4d\0\u0114"+
"\0\u0114\0\u1c92\0\u0114\0\u1cd7\0\u0114\0\u0114\0\u0114";
"\0\u0a83\0\105\0\u0ac8\0\u03c6\0\105\0\u040b\0\105\0\u0114"+
"\0\u0b0d\0\u0b52\0\u0114\0\u0b97\0\u0bdc\0\u0c21\0\u0114\0\u0c66"+
"\0\u0cab\0\u0cf0\0\u0d35\0\u0d7a\0\u0dbf\0\u0e04\0\u0e49\0\u0e8e"+
"\0\u0ed3\0\105\0\105\0\105\0\105\0\u0f18\0\u0f5d\0\u0f5d"+
"\0\u092a\0\u096f\0\u0fa2\0\u0fe7\0\u102c\0\u0114\0\u1071\0\u10b6"+
"\0\u10fb\0\u1140\0\u1185\0\u11ca\0\u120f\0\u1254\0\u1299\0\u12de"+
"\0\u1323\0\u1368\0\u13ad\0\u13f2\0\u1437\0\u0114\0\u0ac8\0\u147c"+
"\0\u14c1\0\u1506\0\u154b\0\u1590\0\u15d5\0\u161a\0\u0114\0\u165f"+
"\0\u16a4\0\u0114\0\u16e9\0\u0114\0\u0114\0\u172e\0\u1773\0\u17b8"+
"\0\u17fd\0\u1842\0\u1887\0\u18cc\0\u1911\0\u1956\0\u199b\0\u19e0"+
"\0\u0114\0\u1a25\0\u0114\0\u1a6a\0\u1aaf\0\u0114\0\u0114\0\u0114"+
"\0\u1af4\0\u1b39\0\u1b7e\0\u0114\0\u1bc3\0\u0114\0\u1c08\0\u1c4d"+
"\0\u0114\0\u0114\0\u1c92\0\u0114\0\u1cd7\0\u0114\0\u0114\0\u0114";
private static int [] zzUnpackRowMap() {
int [] result = new int[167];
int [] result = new int[168];
int offset = 0;
offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);
return result;
@ -139,114 +139,134 @@ public class _HaskellLexer implements FlexLexer {
private static final int [] ZZ_TRANS = zzUnpackTrans();
private static final String ZZ_TRANS_PACKED_0 =
"\1\2\1\3\1\4\2\3\1\5\1\6\1\7\1\10"+
"\1\6\1\7\1\11\1\6\1\7\1\10\1\12\1\7"+
"\1\13\1\14\1\15\1\7\1\16\1\17\1\20\1\21"+
"\1\22\1\23\1\24\1\25\1\26\1\27\1\30\1\31"+
"\1\32\1\33\1\34\1\35\1\36\1\37\1\40\1\41"+
"\1\42\1\43\1\44\1\45\1\46\1\47\1\50\1\51"+
"\1\52\1\6\1\53\1\6\1\54\1\55\1\56\1\57"+
"\1\60\1\61\1\6\1\62\1\63\2\6\1\64\1\6"+
"\1\65\1\6\1\66\110\0\1\3\101\0\2\67\3\0"+
"\1\3\14\67\1\0\62\67\5\0\14\6\2\0\2\6"+
"\34\0\24\6\6\0\2\7\1\0\2\7\1\0\2\7"+
"\1\0\2\7\2\0\2\7\34\0\24\7\10\0\1\10"+
"\1\2\1\3\1\4\1\5\1\6\1\7\1\10\1\6"+
"\1\7\1\11\1\6\1\7\1\10\1\12\1\7\1\13"+
"\1\14\1\15\1\7\1\16\1\17\1\20\1\21\1\3"+
"\1\22\1\23\1\6\1\24\1\6\1\25\1\26\1\27"+
"\1\30\1\31\1\32\1\6\1\33\1\34\2\6\1\35"+
"\1\6\1\36\1\6\1\37\1\40\1\41\1\42\1\43"+
"\1\44\1\45\1\46\1\47\1\50\1\51\1\52\1\53"+
"\1\54\1\55\1\56\1\57\1\60\1\61\1\62\1\63"+
"\1\64\1\65\1\66\1\67\106\0\1\3\25\0\1\3"+
"\60\0\1\5\105\0\13\6\2\0\2\6\3\0\1\6"+
"\2\0\24\6\34\0\2\7\1\0\2\7\1\0\2\7"+
"\1\0\2\7\2\0\2\7\6\0\24\7\36\0\1\10"+
"\2\0\1\10\2\0\1\10\3\0\1\70\2\71\70\0"+
"\1\10\2\0\1\10\2\72\1\10\2\73\1\0\1\70"+
"\2\71\65\0\14\6\2\0\2\6\34\0\6\6\1\74"+
"\15\6\10\0\1\75\2\0\1\75\2\0\1\75\3\0"+
"\1\76\62\0\3\77\1\0\101\77\5\0\14\6\2\0"+
"\2\6\34\0\4\6\1\100\17\6\10\0\1\75\2\0"+
"\1\75\2\0\1\75\3\0\1\76\2\0\1\101\14\0"+
"\1\102\67\0\1\103\57\0\2\104\3\0\15\104\1\0"+
"\5\104\1\105\54\104\37\0\1\106\72\0\1\107\133\0"+
"\1\110\72\0\1\111\47\0\14\6\2\0\2\6\34\0"+
"\1\6\1\112\22\6\5\0\14\6\2\0\2\6\34\0"+
"\3\6\1\113\20\6\5\0\14\6\2\0\1\114\1\6"+
"\34\0\24\6\5\0\14\6\2\0\2\6\34\0\6\6"+
"\1\115\2\6\1\116\5\6\1\117\4\6\5\0\12\6"+
"\1\120\1\6\2\0\2\6\34\0\24\6\5\0\12\6"+
"\1\121\1\6\2\0\1\122\1\6\34\0\1\123\23\6"+
"\5\0\14\6\2\0\2\6\34\0\5\6\1\124\16\6"+
"\5\0\14\6\2\0\1\125\1\6\34\0\24\6\5\0"+
"\14\6\2\0\2\6\34\0\1\126\3\6\1\127\17\6"+
"\5\0\14\6\2\0\2\6\34\0\10\6\1\130\11\6"+
"\1\131\1\6\5\0\12\6\1\132\1\6\2\0\2\6"+
"\34\0\24\6\5\0\14\6\2\0\2\6\34\0\10\6"+
"\1\133\13\6\2\67\3\0\1\134\14\67\1\0\62\67"+
"\3\135\1\0\101\135\10\0\1\136\2\0\1\136\2\0"+
"\1\136\2\0\1\137\3\0\1\137\67\0\4\140\2\0"+
"\1\140\4\0\2\140\34\0\1\140\5\0\2\140\3\0"+
"\1\140\23\0\1\141\2\0\1\141\76\0\1\75\2\0"+
"\1\75\2\0\1\75\3\0\1\70\2\71\70\0\1\135"+
"\2\0\1\135\2\0\1\135\73\0\14\6\2\0\2\6"+
"\34\0\1\6\1\142\22\6\2\101\2\0\101\101\25\103"+
"\1\143\57\103\5\0\14\6\2\0\2\6\34\0\1\144"+
"\23\6\5\0\14\6\2\0\2\6\34\0\14\6\1\145"+
"\7\6\5\0\14\6\2\0\2\6\34\0\1\6\1\146"+
"\4\6\1\147\15\6\5\0\14\6\2\0\2\6\34\0"+
"\20\6\1\150\3\6\5\0\14\6\2\0\2\6\34\0"+
"\15\6\1\151\6\6\5\0\14\6\2\0\2\6\34\0"+
"\6\6\1\152\6\6\1\153\6\6\5\0\14\6\2\0"+
"\2\6\34\0\14\6\1\154\7\6\5\0\14\6\2\0"+
"\2\6\34\0\7\6\1\155\14\6\5\0\14\6\2\0"+
"\2\6\34\0\21\6\1\156\2\6\5\0\14\6\2\0"+
"\2\6\34\0\1\6\1\157\22\6\5\0\14\6\2\0"+
"\2\6\34\0\1\160\23\6\5\0\14\6\2\0\1\161"+
"\1\6\34\0\24\6\5\0\14\6\2\0\2\6\34\0"+
"\20\6\1\162\3\6\5\0\14\6\2\0\2\6\34\0"+
"\7\6\1\163\14\6\5\0\14\6\2\0\1\164\1\6"+
"\34\0\24\6\10\0\1\135\2\0\1\135\2\0\1\135"+
"\4\0\2\71\70\0\1\136\2\0\1\136\2\0\1\136"+
"\73\0\14\6\2\0\1\165\1\6\34\0\24\6\25\103"+
"\1\143\1\103\1\166\55\103\5\0\14\6\2\0\2\6"+
"\34\0\4\6\1\167\17\6\5\0\14\6\2\0\2\6"+
"\34\0\14\6\1\170\7\6\5\0\14\6\2\0\2\6"+
"\34\0\5\6\1\171\16\6\5\0\12\6\1\172\1\6"+
"\2\0\2\6\34\0\24\6\5\0\14\6\2\0\1\173"+
"\1\6\34\0\24\6\5\0\14\6\2\0\2\6\34\0"+
"\1\174\23\6\5\0\14\6\2\0\2\6\34\0\5\6"+
"\1\175\16\6\5\0\14\6\2\0\2\6\34\0\1\176"+
"\23\6\5\0\14\6\2\0\2\6\34\0\5\6\1\177"+
"\16\6\5\0\14\6\2\0\2\6\34\0\14\6\1\200"+
"\7\6\5\0\14\6\2\0\1\201\1\6\34\0\24\6"+
"\5\0\14\6\2\0\2\6\34\0\1\6\1\202\22\6"+
"\5\0\14\6\2\0\2\6\34\0\11\6\1\203\12\6"+
"\5\0\14\6\2\0\1\204\1\6\34\0\24\6\5\0"+
"\14\6\2\0\2\6\34\0\3\6\1\205\20\6\5\0"+
"\14\6\2\0\2\6\34\0\15\6\1\206\6\6\5\0"+
"\14\6\2\0\2\6\34\0\5\6\1\207\16\6\5\0"+
"\14\6\2\0\2\6\34\0\1\210\23\6\5\0\7\6"+
"\1\211\4\6\2\0\2\6\34\0\24\6\5\0\14\6"+
"\2\0\2\6\34\0\15\6\1\212\6\6\5\0\14\6"+
"\2\0\2\6\34\0\5\6\1\213\16\6\5\0\14\6"+
"\2\0\2\6\34\0\3\6\1\214\20\6\5\0\14\6"+
"\2\0\2\6\34\0\16\6\1\215\5\6\5\0\14\6"+
"\2\0\2\6\34\0\11\6\1\216\12\6\5\0\14\6"+
"\2\0\2\6\34\0\22\6\1\217\1\6\5\0\14\6"+
"\2\0\2\6\34\0\1\6\1\220\22\6\5\0\14\6"+
"\2\0\2\6\34\0\4\6\1\221\17\6\5\0\14\6"+
"\2\0\1\222\1\6\34\0\24\6\5\0\14\6\2\0"+
"\2\6\34\0\6\6\1\223\15\6\5\0\14\6\2\0"+
"\2\6\34\0\11\6\1\224\12\6\5\0\14\6\2\0"+
"\2\6\34\0\4\6\1\225\10\6\1\226\6\6\5\0"+
"\14\6\2\0\2\6\34\0\14\6\1\227\7\6\5\0"+
"\14\6\2\0\2\6\34\0\12\6\1\230\11\6\5\0"+
"\14\6\2\0\2\6\34\0\4\6\1\231\17\6\5\0"+
"\14\6\2\0\2\6\34\0\5\6\1\232\16\6\5\0"+
"\14\6\2\0\2\6\34\0\12\6\1\233\11\6\5\0"+
"\14\6\2\0\2\6\34\0\20\6\1\234\3\6\5\0"+
"\14\6\2\0\1\235\1\6\34\0\24\6\5\0\14\6"+
"\2\0\2\6\34\0\5\6\1\236\16\6\5\0\14\6"+
"\2\0\2\6\34\0\13\6\1\237\10\6\5\0\14\6"+
"\2\0\2\6\34\0\11\6\1\240\12\6\5\0\14\6"+
"\2\0\2\6\34\0\14\6\1\241\7\6\5\0\14\6"+
"\2\0\2\6\34\0\11\6\1\242\12\6\5\0\14\6"+
"\2\0\1\243\1\6\34\0\24\6\5\0\14\6\2\0"+
"\1\244\1\6\34\0\24\6\5\0\14\6\2\0\1\245"+
"\1\6\34\0\24\6\5\0\14\6\2\0\2\6\34\0"+
"\12\6\1\246\11\6\5\0\14\6\2\0\2\6\34\0"+
"\7\6\1\247\14\6";
"\2\71\66\0\13\6\2\0\2\6\3\0\1\6\2\0"+
"\6\6\1\74\15\6\36\0\1\75\2\0\1\75\2\0"+
"\1\75\3\0\1\76\64\0\3\77\1\0\101\77\4\0"+
"\13\6\2\0\2\6\3\0\1\6\2\0\4\6\1\100"+
"\17\6\36\0\1\75\2\0\1\75\2\0\1\75\3\0"+
"\1\76\2\0\1\101\42\0\1\102\41\0\1\103\61\0"+
"\2\104\2\0\14\104\1\0\5\104\1\105\1\0\55\104"+
"\2\106\2\0\14\106\1\0\6\106\1\0\1\107\54\106"+
"\4\0\13\6\2\0\2\6\3\0\1\6\2\0\1\6"+
"\1\110\22\6\34\0\13\6\2\0\2\6\3\0\1\6"+
"\2\0\3\6\1\111\20\6\34\0\13\6\2\0\1\112"+
"\1\6\3\0\1\6\2\0\24\6\34\0\13\6\2\0"+
"\2\6\3\0\1\6\2\0\6\6\1\113\2\6\1\114"+
"\5\6\1\115\4\6\34\0\11\6\1\116\1\6\2\0"+
"\2\6\3\0\1\6\2\0\24\6\34\0\11\6\1\117"+
"\1\6\2\0\1\120\1\6\3\0\1\6\2\0\1\121"+
"\23\6\34\0\13\6\2\0\2\6\3\0\1\6\2\0"+
"\5\6\1\122\16\6\34\0\13\6\2\0\1\123\1\6"+
"\3\0\1\6\2\0\24\6\34\0\13\6\2\0\2\6"+
"\3\0\1\6\2\0\1\124\3\6\1\125\17\6\34\0"+
"\13\6\2\0\2\6\3\0\1\6\2\0\10\6\1\126"+
"\11\6\1\127\1\6\34\0\11\6\1\130\1\6\2\0"+
"\2\6\3\0\1\6\2\0\24\6\34\0\13\6\2\0"+
"\2\6\3\0\1\6\2\0\10\6\1\131\13\6\113\0"+
"\1\132\44\0\1\133\161\0\1\134\72\0\1\135\16\0"+
"\3\136\1\0\101\136\6\0\1\137\2\0\1\137\2\0"+
"\1\137\2\0\1\140\3\0\1\140\67\0\4\141\2\0"+
"\1\141\4\0\2\141\6\0\1\141\5\0\2\141\3\0"+
"\1\141\51\0\1\142\2\0\1\142\76\0\1\75\2\0"+
"\1\75\2\0\1\75\3\0\1\70\2\71\70\0\1\136"+
"\2\0\1\136\2\0\1\136\74\0\13\6\2\0\2\6"+
"\3\0\1\6\2\0\1\6\1\143\22\6\30\0\2\101"+
"\2\0\101\101\23\103\1\144\61\103\4\0\13\6\2\0"+
"\2\6\3\0\1\6\2\0\1\145\23\6\34\0\13\6"+
"\2\0\2\6\3\0\1\6\2\0\14\6\1\146\7\6"+
"\34\0\13\6\2\0\2\6\3\0\1\6\2\0\1\6"+
"\1\147\4\6\1\150\15\6\34\0\13\6\2\0\2\6"+
"\3\0\1\6\2\0\20\6\1\151\3\6\34\0\13\6"+
"\2\0\2\6\3\0\1\6\2\0\15\6\1\152\6\6"+
"\34\0\13\6\2\0\2\6\3\0\1\6\2\0\6\6"+
"\1\153\6\6\1\154\6\6\34\0\13\6\2\0\2\6"+
"\3\0\1\6\2\0\14\6\1\155\7\6\34\0\13\6"+
"\2\0\2\6\3\0\1\6\2\0\7\6\1\156\14\6"+
"\34\0\13\6\2\0\2\6\3\0\1\6\2\0\21\6"+
"\1\157\2\6\34\0\13\6\2\0\2\6\3\0\1\6"+
"\2\0\1\6\1\160\22\6\34\0\13\6\2\0\2\6"+
"\3\0\1\6\2\0\1\161\23\6\34\0\13\6\2\0"+
"\1\162\1\6\3\0\1\6\2\0\24\6\34\0\13\6"+
"\2\0\2\6\3\0\1\6\2\0\20\6\1\163\3\6"+
"\34\0\13\6\2\0\2\6\3\0\1\6\2\0\7\6"+
"\1\164\14\6\34\0\13\6\2\0\1\165\1\6\3\0"+
"\1\6\2\0\24\6\36\0\1\136\2\0\1\136\2\0"+
"\1\136\4\0\2\71\70\0\1\137\2\0\1\137\2\0"+
"\1\137\74\0\13\6\2\0\1\166\1\6\3\0\1\6"+
"\2\0\24\6\30\0\23\103\1\144\1\103\1\167\57\103"+
"\4\0\13\6\2\0\2\6\3\0\1\6\2\0\4\6"+
"\1\170\17\6\34\0\13\6\2\0\2\6\3\0\1\6"+
"\2\0\14\6\1\171\7\6\34\0\13\6\2\0\2\6"+
"\3\0\1\6\2\0\5\6\1\172\16\6\34\0\11\6"+
"\1\173\1\6\2\0\2\6\3\0\1\6\2\0\24\6"+
"\34\0\13\6\2\0\1\174\1\6\3\0\1\6\2\0"+
"\24\6\34\0\13\6\2\0\2\6\3\0\1\6\2\0"+
"\1\175\23\6\34\0\13\6\2\0\2\6\3\0\1\6"+
"\2\0\5\6\1\176\16\6\34\0\13\6\2\0\2\6"+
"\3\0\1\6\2\0\1\177\23\6\34\0\13\6\2\0"+
"\2\6\3\0\1\6\2\0\5\6\1\200\16\6\34\0"+
"\13\6\2\0\2\6\3\0\1\6\2\0\14\6\1\201"+
"\7\6\34\0\13\6\2\0\1\202\1\6\3\0\1\6"+
"\2\0\24\6\34\0\13\6\2\0\2\6\3\0\1\6"+
"\2\0\1\6\1\203\22\6\34\0\13\6\2\0\2\6"+
"\3\0\1\6\2\0\11\6\1\204\12\6\34\0\13\6"+
"\2\0\1\205\1\6\3\0\1\6\2\0\24\6\34\0"+
"\13\6\2\0\2\6\3\0\1\6\2\0\3\6\1\206"+
"\20\6\34\0\13\6\2\0\2\6\3\0\1\6\2\0"+
"\15\6\1\207\6\6\34\0\13\6\2\0\2\6\3\0"+
"\1\6\2\0\5\6\1\210\16\6\34\0\13\6\2\0"+
"\2\6\3\0\1\6\2\0\1\211\23\6\34\0\6\6"+
"\1\212\4\6\2\0\2\6\3\0\1\6\2\0\24\6"+
"\34\0\13\6\2\0\2\6\3\0\1\6\2\0\15\6"+
"\1\213\6\6\34\0\13\6\2\0\2\6\3\0\1\6"+
"\2\0\5\6\1\214\16\6\34\0\13\6\2\0\2\6"+
"\3\0\1\6\2\0\3\6\1\215\20\6\34\0\13\6"+
"\2\0\2\6\3\0\1\6\2\0\16\6\1\216\5\6"+
"\34\0\13\6\2\0\2\6\3\0\1\6\2\0\11\6"+
"\1\217\12\6\34\0\13\6\2\0\2\6\3\0\1\6"+
"\2\0\22\6\1\220\1\6\34\0\13\6\2\0\2\6"+
"\3\0\1\6\2\0\1\6\1\221\22\6\34\0\13\6"+
"\2\0\2\6\3\0\1\6\2\0\4\6\1\222\17\6"+
"\34\0\13\6\2\0\1\223\1\6\3\0\1\6\2\0"+
"\24\6\34\0\13\6\2\0\2\6\3\0\1\6\2\0"+
"\6\6\1\224\15\6\34\0\13\6\2\0\2\6\3\0"+
"\1\6\2\0\11\6\1\225\12\6\34\0\13\6\2\0"+
"\2\6\3\0\1\6\2\0\4\6\1\226\10\6\1\227"+
"\6\6\34\0\13\6\2\0\2\6\3\0\1\6\2\0"+
"\14\6\1\230\7\6\34\0\13\6\2\0\2\6\3\0"+
"\1\6\2\0\12\6\1\231\11\6\34\0\13\6\2\0"+
"\2\6\3\0\1\6\2\0\4\6\1\232\17\6\34\0"+
"\13\6\2\0\2\6\3\0\1\6\2\0\5\6\1\233"+
"\16\6\34\0\13\6\2\0\2\6\3\0\1\6\2\0"+
"\12\6\1\234\11\6\34\0\13\6\2\0\2\6\3\0"+
"\1\6\2\0\20\6\1\235\3\6\34\0\13\6\2\0"+
"\1\236\1\6\3\0\1\6\2\0\24\6\34\0\13\6"+
"\2\0\2\6\3\0\1\6\2\0\5\6\1\237\16\6"+
"\34\0\13\6\2\0\2\6\3\0\1\6\2\0\13\6"+
"\1\240\10\6\34\0\13\6\2\0\2\6\3\0\1\6"+
"\2\0\11\6\1\241\12\6\34\0\13\6\2\0\2\6"+
"\3\0\1\6\2\0\14\6\1\242\7\6\34\0\13\6"+
"\2\0\2\6\3\0\1\6\2\0\11\6\1\243\12\6"+
"\34\0\13\6\2\0\1\244\1\6\3\0\1\6\2\0"+
"\24\6\34\0\13\6\2\0\1\245\1\6\3\0\1\6"+
"\2\0\24\6\34\0\13\6\2\0\1\246\1\6\3\0"+
"\1\6\2\0\24\6\34\0\13\6\2\0\2\6\3\0"+
"\1\6\2\0\12\6\1\247\11\6\34\0\13\6\2\0"+
"\2\6\3\0\1\6\2\0\7\6\1\250\14\6\30\0";
private static int [] zzUnpackTrans() {
int [] result = new int[7452];
@ -290,13 +310,13 @@ public class _HaskellLexer implements FlexLexer {
private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute();
private static final String ZZ_ATTRIBUTE_PACKED_0 =
"\1\0\2\11\14\1\1\11\1\1\6\11\1\1\1\11"+
"\1\1\12\11\2\1\3\11\15\1\5\0\2\1\2\0"+
"\2\1\1\11\2\0\5\11\22\1\1\11\2\1\1\0"+
"\3\1\1\0\104\1";
"\1\0\1\11\2\1\1\11\12\1\1\11\17\1\6\11"+
"\1\1\1\11\1\1\12\11\2\1\3\11\4\0\2\1"+
"\2\0\2\1\1\11\2\0\1\11\1\0\1\11\22\1"+
"\4\11\2\1\1\0\3\1\1\0\104\1";
private static int [] zzUnpackAttribute() {
int [] result = new int[167];
int [] result = new int[168];
int offset = 0;
offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);
return result;
@ -591,294 +611,298 @@ public class _HaskellLexer implements FlexLexer {
zzMarkedPos = zzMarkedPosL;
switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) {
case 56:
case 57:
{ return HS_CASE;
}
case 73: break;
case 50:
case 74: break;
case 51:
{ return HS_HEXADECIMAL;
}
case 74: break;
case 38:
case 75: break;
case 39:
{ return HS_COMMENT;
}
case 75: break;
case 43:
case 76: break;
case 49:
{ return HS_COLON_COLON;
}
case 76: break;
case 60:
case 77: break;
case 61:
{ return HS_CLASS;
}
case 77: break;
case 72:
case 78: break;
case 73:
{ return HS_QUALIFIED;
}
case 78: break;
case 69:
case 79: break;
case 70:
{ return HS_NEWTYPE;
}
case 79: break;
case 33:
case 80: break;
case 35:
{ return HS_AT;
}
case 80: break;
case 41:
case 81: break;
case 47:
{ return HS_DOT_DOT;
}
case 81: break;
case 46:
case 82: break;
case 44:
{ return HS_IF;
}
case 82: break;
case 26:
{ return HS_SEMICOLON;
}
case 83: break;
case 59:
{ return HS_INFIX;
case 3:
{ return HS_NEWLINE;
}
case 84: break;
case 45:
{ return HS_AS;
case 28:
{ return HS_SEMICOLON;
}
case 85: break;
case 37:
{ return HS_FLOAT;
case 60:
{ return HS_INFIX;
}
case 86: break;
case 24:
{ return HS_RIGHT_PAREN;
case 2:
{ return com.intellij.psi.TokenType.WHITE_SPACE;
}
case 87: break;
case 54:
{ return HS_NCOMMENT;
case 43:
{ return HS_AS;
}
case 88: break;
case 34:
{ return HS_TILDE;
case 38:
{ return HS_FLOAT;
}
case 89: break;
case 8:
{ return HS_DASH;
case 26:
{ return HS_RIGHT_PAREN;
}
case 90: break;
case 5:
{ return HS_DECIMAL;
case 55:
{ return HS_NCOMMENT;
}
case 91: break;
case 52:
{ return HS_LET;
case 36:
{ return HS_TILDE;
}
case 92: break;
case 18:
{ return HS_SLASH;
case 9:
{ return HS_DASH;
}
case 93: break;
case 61:
{ return HS_WHERE;
case 6:
{ return HS_DECIMAL;
}
case 94: break;
case 11:
{ return HS_EXCLAMATION_MARK;
case 53:
{ return HS_LET;
}
case 95: break;
case 40:
{ return HS_STRING_LITERAL;
case 20:
{ return HS_SLASH;
}
case 96: break;
case 42:
{ return HS_LEFT_ARROW;
case 62:
{ return HS_WHERE;
}
case 97: break;
case 66:
{ return HS_MODULE;
case 13:
{ return HS_EXCLAMATION_MARK;
}
case 98: break;
case 9:
{ return HS_LEFT_BRACE;
case 42:
{ return HS_STRING_LITERAL;
}
case 99: break;
case 55:
{ return HS_DATA;
case 48:
{ return HS_LEFT_ARROW;
}
case 100: break;
case 49:
{ return HS_CHARACTER_LITERAL;
case 67:
{ return HS_MODULE;
}
case 101: break;
case 3:
{ return HS_VAR_ID;
case 10:
{ return HS_LEFT_BRACE;
}
case 102: break;
case 35:
{ return HS_UNDERSCORE;
case 56:
{ return HS_DATA;
}
case 103: break;
case 6:
{ return HS_PLUS;
case 41:
{ return HS_CHARACTER_LITERAL;
}
case 104: break;
case 15:
{ return HS_AMPERSAND;
case 4:
{ return HS_VAR_ID;
}
case 105: break;
case 32:
{ return HS_VERTICAL_BAR;
case 12:
{ return HS_UNDERSCORE;
}
case 106: break;
case 58:
{ return HS_TYPE;
case 7:
{ return HS_PLUS;
}
case 107: break;
case 13:
{ return HS_DOLLAR;
case 17:
{ return HS_AMPERSAND;
}
case 108: break;
case 12:
{ return HS_HASH;
case 34:
{ return HS_VERTICAL_BAR;
}
case 109: break;
case 65:
{ return HS_HIDING;
case 59:
{ return HS_TYPE;
}
case 110: break;
case 14:
{ return HS_PERCENTAGE;
case 15:
{ return HS_DOLLAR;
}
case 111: break;
case 30:
{ return HS_COLON;
case 14:
{ return HS_HASH;
}
case 112: break;
case 70:
{ return HS_INSTANCE;
case 33:
{ return HS_EQUAL;
}
case 113: break;
case 28:
{ return HS_RIGHT_BRACKET;
case 66:
{ return HS_HIDING;
}
case 114: break;
case 23:
{ return HS_LEFT_PAREN;
case 16:
{ return HS_PERCENTAGE;
}
case 115: break;
case 29:
{ return HS_BACKQUOTE;
case 32:
{ return HS_COLON;
}
case 116: break;
case 19:
{ return HS_LT;
case 71:
{ return HS_INSTANCE;
}
case 117: break;
case 27:
{ return HS_LEFT_BRACKET;
case 30:
{ return HS_RIGHT_BRACKET;
}
case 118: break;
case 21:
{ return HS_QUESTION_MARK;
case 25:
{ return HS_LEFT_PAREN;
}
case 119: break;
case 62:
{ return HS_INFIXL;
case 31:
{ return HS_BACKQUOTE;
}
case 120: break;
case 64:
{ return HS_IMPORT;
case 21:
{ return HS_LT;
}
case 121: break;
case 71:
{ return HS_DERIVING;
case 29:
{ return HS_LEFT_BRACKET;
}
case 122: break;
case 4:
{ return HS_CON_ID;
case 23:
{ return HS_QUESTION_MARK;
}
case 123: break;
case 48:
{ return HS_DO;
case 63:
{ return HS_INFIXL;
}
case 124: break;
case 17:
{ return HS_DOT;
case 65:
{ return HS_IMPORT;
}
case 125: break;
case 47:
{ return HS_IN;
case 72:
{ return HS_DERIVING;
}
case 126: break;
case 51:
{ return HS_OCTAL;
case 5:
{ return HS_CON_ID;
}
case 127: break;
case 63:
{ return HS_INFIXR;
case 46:
{ return HS_DO;
}
case 128: break;
case 22:
{ return HS_CARET;
case 19:
{ return HS_DOT;
}
case 129: break;
case 45:
{ return HS_IN;
}
case 130: break;
case 52:
{ return HS_OCTAL;
}
case 131: break;
case 64:
{ return HS_INFIXR;
}
case 132: break;
case 24:
{ return HS_CARET;
}
case 133: break;
case 1:
{ return com.intellij.psi.TokenType.BAD_CHARACTER;
}
case 130: break;
case 68:
case 134: break;
case 69:
{ return HS_DEFAULT;
}
case 131: break;
case 44:
case 135: break;
case 50:
{ return HS_DOUBLE_RIGHT_ARROW;
}
case 132: break;
case 53:
case 136: break;
case 54:
{ return HS_ELSE;
}
case 133: break;
case 25:
case 137: break;
case 27:
{ return HS_COMMA;
}
case 134: break;
case 20:
case 138: break;
case 22:
{ return HS_GT;
}
case 135: break;
case 31:
{ return HS_DEFINED_BY;
}
case 136: break;
case 16:
case 139: break;
case 18:
{ return HS_STAR;
}
case 137: break;
case 7:
case 140: break;
case 8:
{ return HS_BACKSLASH;
}
case 138: break;
case 2:
{ return HS_WHITE_CHAR;
}
case 139: break;
case 36:
case 141: break;
case 37:
{ return HS_OF;
}
case 140: break;
case 67:
case 142: break;
case 68:
{ return HS_FOREIGN;
}
case 141: break;
case 57:
case 143: break;
case 58:
{ return HS_THEN;
}
case 142: break;
case 39:
case 144: break;
case 40:
{ return HS_RIGHT_ARROW;
}
case 143: break;
case 10:
case 145: break;
case 11:
{ return HS_RIGHT_BRACE;
}
case 144: break;
case 146: break;
default:
if (zzInput == YYEOF && zzStartRead == zzCurrentPos) {
zzAtEOF = true;

View File

@ -16,26 +16,17 @@
package com.powertuple.intellij.haskell.annotator
import com.intellij.lang.annotation.{AnnotationHolder, ExternalAnnotator}
import com.intellij.notification.NotificationGroup
import com.intellij.openapi.diagnostic.Logger
import com.intellij.psi.PsiFile
import com.intellij.openapi.util.TextRange
import com.intellij.openapi.application.{ModalityState, ApplicationManager}
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.execution.process.ProcessOutput
import com.intellij.openapi.util.text.StringUtil
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl
import com.intellij.openapi.ui.MessageType
import scala.collection.JavaConversions._
import com.intellij.lang.annotation.{AnnotationHolder, ExternalAnnotator}
import com.intellij.openapi.application.{ApplicationManager, ModalityState}
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiFile
import com.powertuple.intellij.haskell.HaskellFileType
import com.powertuple.intellij.haskell.external.GhciModManager
class GhcModiExternalAnnotator extends ExternalAnnotator[GhcModInitialInfo, GhcModResult] {
private val Log = Logger.getInstance(classOf[GhcModiExternalAnnotator])
private val GhcModNotificationGroup = NotificationGroup.balloonGroup("Ghc-mod inspections")
class GhcModiExternalAnnotator extends ExternalAnnotator[GhcModInitialInfo, GhcModiResult] {
/**
* Returning null will cause doAnnotate() not to be called by Intellij API.
@ -50,7 +41,7 @@ class GhcModiExternalAnnotator extends ExternalAnnotator[GhcModInitialInfo, GhcM
}
}
override def doAnnotate(initialInfoGhcMod: GhcModInitialInfo): GhcModResult = {
override def doAnnotate(initialInfoGhcMod: GhcModInitialInfo): GhcModiResult = {
ApplicationManager.getApplication.invokeAndWait(new Runnable() {
override def run() {
FileDocumentManager.getInstance.saveDocument(FileDocumentManager.getInstance().getDocument(initialInfoGhcMod.psiFile.getVirtualFile))
@ -58,16 +49,16 @@ class GhcModiExternalAnnotator extends ExternalAnnotator[GhcModInitialInfo, GhcM
}, ModalityState.any())
val ghcModi = GhciModManager.getGhcMod(initialInfoGhcMod.psiFile.getProject)
val ghcModOutput = ghcModi.execute("check " + initialInfoGhcMod.filePath)
val ghcModiOutput = ghcModi.execute("check " + initialInfoGhcMod.filePath)
if (ghcModOutput.outputLines.isEmpty) {
new GhcModResult(Seq())
if (ghcModiOutput.outputLines.isEmpty) {
new GhcModiResult(Seq())
} else {
new GhcModResult(ghcModOutput.outputLines.map(parseGhcModOutputLine))
new GhcModiResult(ghcModiOutput.outputLines.map(parseGhcModiOutputLine))
}
}
override def apply(psiFile: PsiFile, ghcModResult: GhcModResult, holder: AnnotationHolder) {
override def apply(psiFile: PsiFile, ghcModResult: GhcModiResult, holder: AnnotationHolder) {
if (ghcModResult.problems.nonEmpty && psiFile.isValid) {
for (annotation <- createAnnotations(ghcModResult, psiFile.getText)) {
annotation match {
@ -85,20 +76,15 @@ class GhcModiExternalAnnotator extends ExternalAnnotator[GhcModInitialInfo, GhcM
fileStatusMap.markFileScopeDirty(document, new TextRange(0, document.getTextLength), psiFile.getTextLength)
}
private def startOffSetForProblem(lengthPerLine: Array[Int], problem: GhcModProblem): Int = {
val lineNr = problem.lineNr
(if (lineNr <= 1) {
0
} else {
lengthPerLine.take(lineNr - 1).sum
}) + problem.columnNr - 1
private def startOffSetForProblem(lengthPerLine: Iterator[Int], problem: GhcModiProblem): Int = {
lengthPerLine.take(problem.lineNr - 1).map(_ + 1).sum + problem.columnNr
}
private[annotator] def createAnnotations(ghcModResult: GhcModResult, text: String): Seq[Annotation] = {
val lengthPerLine = StringUtil.splitByLines(text, false).map(_.size + 1)
private[annotator] def createAnnotations(ghcModResult: GhcModiResult, text: String): Seq[Annotation] = {
val lengthPerLine = text.lines.map(_.size)
for (problem <- ghcModResult.problems) yield {
val startOffSet = startOffSetForProblem(lengthPerLine, problem)
val textRange = TextRange.create(startOffSet, startOffSet + 1)
val textRange = TextRange.create(startOffSet - 1, startOffSet)
if (problem.description.startsWith("Warning:")) {
WarningAnnotation(textRange, problem.description)
} else {
@ -107,25 +93,18 @@ class GhcModiExternalAnnotator extends ExternalAnnotator[GhcModInitialInfo, GhcM
}
}
private[annotator] def parseGhcModOutput(ghcModOutput: ProcessOutput): Seq[GhcModProblem] = {
ghcModOutput match {
case gmo if !gmo.getStderrLines.isEmpty => GhcModNotificationGroup.createNotification(s"Ghc-mod error output: ${gmo.getStderr}", MessageType.ERROR); Seq()
case gmo => gmo.getStdoutLines.map(parseGhcModOutputLine)
}
}
private def parseGhcModOutputLine(ghcModOutput: String): GhcModProblem = {
private[annotator] def parseGhcModiOutputLine(ghcModOutput: String): GhcModiProblem = {
val ghcModProblemPattern = """.+:([\d]+):([\d]+):(.+)""".r
val ghcModProblemPattern(lineNr, columnNr, description) = ghcModOutput
new GhcModProblem(lineNr.toInt, columnNr.toInt - 1, description)
new GhcModiProblem(lineNr.toInt, columnNr.toInt, description)
}
}
case class GhcModInitialInfo(psiFile: PsiFile, filePath: String)
case class GhcModResult(problems: Seq[GhcModProblem] = Seq())
case class GhcModiResult(problems: Seq[GhcModiProblem] = Seq())
case class GhcModProblem(lineNr: Int, columnNr: Int, description: String)
case class GhcModiProblem(lineNr: Int, columnNr: Int, description: String)
abstract class Annotation

View File

@ -17,10 +17,11 @@
package com.powertuple.intellij.haskell.external
import java.io._
import java.util.concurrent.Executors
import java.util.concurrent.{Executors, TimeoutException}
import com.intellij.openapi.components.ProjectComponent
import com.intellij.openapi.project.Project
import com.powertuple.intellij.haskell.HaskellNotificationGroup
import com.powertuple.intellij.haskell.settings.HaskellSettings
import scala.collection.mutable.ListBuffer
@ -41,7 +42,6 @@ class GhcModi(val project: Project, val settings: HaskellSettings) extends Proje
def reportFailure(t: Throwable) {}
}
private[this] var process: Process = _
private[this] var outputStream: OutputStream = _
private[this] val stdOutListBuffer = ListBuffer[String]()
private[this] val stdErrListBuffer = ListBuffer[String]()
@ -49,51 +49,79 @@ class GhcModi(val project: Project, val settings: HaskellSettings) extends Proje
private val OK = "OK"
def execute(command: String): GhcModiOutput = synchronized {
if (outputStream == null) {
// creating Process has failed in #startGhcModi
return GhcModiOutput()
}
stdOutListBuffer.clear()
stdErrListBuffer.clear()
try {
outputStream.write((command + "\n").getBytes)
outputStream.flush()
outputStream.write((command + "\n").getBytes)
outputStream.flush()
val waitForOutput = Future {
while (stdOutListBuffer.lastOption != Some(OK)) {
Thread.sleep(5)
}
}
Await.result(waitForOutput, 2.second)
val waitForOutput = Future {
while (stdOutListBuffer.lastOption != Some(OK)) {
Thread.sleep(5)
if (stdErrListBuffer.nonEmpty) {
HaskellNotificationGroup.notifyError(s"ghc-modi error output: ${stdErrListBuffer.mkString}")
GhcModiOutput()
} else {
GhcModiOutput(stdOutListBuffer.filter(_ != OK))
}
}
catch {
case _: TimeoutException | _: IOException => {
HaskellNotificationGroup.notifyError("Error in communication with ghc-modi. ghc-modi will be restarted.")
reinit()
GhcModiOutput()
}
}
Await.result(waitForOutput, 2.second)
GhcModiOutput(stdOutListBuffer.filter(_ != OK), stdErrListBuffer)
}
def exit() {
outputStream.close()
private def exit() {
if (outputStream != null) {
outputStream.close()
}
}
private def startGhcModi() {
try {
Process(settings.getState.ghcModiPath, new File(project.getBasePath)).run(
new ProcessIO(
stdin => outputStream = stdin,
stdout => Source.fromInputStream(stdout).getLines.foreach(stdOutListBuffer.+=),
stderr => Source.fromInputStream(stderr).getLines.foreach(stdErrListBuffer.+=)
))
}
catch {
case e: IOException => {
HaskellNotificationGroup.notifyError("Can not get connection with ghc-modi. Make sure you have set right path in settings to ghc-modi.")
}
}
}
def reinit() {
exit()
initComponent()
startGhcModi()
}
override def projectOpened(): Unit = {}
override def projectOpened(): Unit = {
startGhcModi()
}
override def projectClosed(): Unit = {
exit()
}
override def initComponent(): Unit = {
Process(settings.getState.ghcModiPath, new File(project.getBasePath)).run(
new ProcessIO(
stdin => outputStream = stdin,
stdout => Source.fromInputStream(stdout).getLines.foreach(stdOutListBuffer.+=),
stderr => Source.fromInputStream(stderr).getLines.foreach(stdErrListBuffer.+=)
))
}
override def initComponent(): Unit = {}
override def disposeComponent(): Unit = {}
override def getComponentName: String = "ghcModi"
}
case class GhcModiOutput(outputLines: Seq[String], errorLines: Seq[String])
case class GhcModiOutput(outputLines: Seq[String] = Seq())

View File

@ -0,0 +1,258 @@
/*
* Copyright 2014 Rik van der Kleij
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.powertuple.intellij.haskell.formatter;
import com.intellij.formatting.*;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.TokenType;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.formatter.FormatterUtil;
import com.intellij.psi.impl.source.tree.FileElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.powertuple.intellij.haskell.formatter.settings.HaskellCodeStyleSettings;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static com.powertuple.intellij.haskell.psi.HaskellTypes.*;
/**
* Formatter which use blank line as start of new definition.
*/
public class HaskellFormattingBlock implements ASTBlock {
@NotNull
protected final ASTNode node;
@Nullable
protected final Wrap wrap;
@Nullable
protected final Alignment alignment;
private final CommonCodeStyleSettings settings;
private final HaskellCodeStyleSettings haskellSettings;
private final SpacingBuilder spacingBuilder;
private List<Block> subBlocks;
private Boolean incomplete;
private boolean indentWithTabSize;
private int indentCounter;
private static final TokenSet ReservedIdsToIndent = TokenSet.create(HS_VERTICAL_BAR);
public static final TokenSet RESERVED_IDS_TO_INDENT = TokenSet.create(HS_WHERE, HS_THEN, HS_DO);
public static final TokenSet RESERVED_IDS_TO_BACK_INDENT = TokenSet.create(HS_ELSE);
private final TokenSet INDENT_PREV_RESERVED_IDS = TokenSet.create(HS_WHERE, HS_DO, HS_THEN, HS_ELSE);
public HaskellFormattingBlock(@NotNull ASTNode node,
@NotNull CommonCodeStyleSettings settings,
@NotNull HaskellCodeStyleSettings haskellSettings,
@NotNull SpacingBuilder spacingBuilder,
@Nullable Wrap wrap,
int indentCounter,
boolean indentWithTabSize,
@Nullable Alignment alignment) {
this.node = node;
this.wrap = wrap;
this.alignment = alignment;
this.settings = settings;
this.haskellSettings = haskellSettings;
this.spacingBuilder = spacingBuilder;
this.indentCounter = indentCounter;
this.indentWithTabSize = indentWithTabSize;
}
@Override
public ASTNode getNode() {
return node;
}
@NotNull
@Override
public TextRange getTextRange() {
return node.getTextRange();
}
@NotNull
@Override
public List<Block> getSubBlocks() {
if (subBlocks == null) {
subBlocks = buildSubBlocks();
}
return new ArrayList<Block>(subBlocks);
}
private List<Block> buildSubBlocks() {
final List<Block> blocks = new ArrayList<Block>();
if (!(node instanceof FileElement)) {
return Collections.unmodifiableList(blocks);
}
ASTNode prevNode = null;
Alignment alignment = null;
boolean startNewlineInDefinition = false;
boolean startOfNewDefinition = false;
boolean notIndentAgain = false;
for (ASTNode child = node.getFirstChildNode(); child != null; child = child.getTreeNext()) {
if (child.getElementType() == HS_NEWLINE) {
if (startNewlineInDefinition) {
startOfNewDefinition = true;
indentCounter = 0;
alignment = null;
notIndentAgain = false;
} else {
startNewlineInDefinition = true;
}
continue;
} else if (child.getElementType() == TokenType.WHITE_SPACE) {
continue;
}
indentWithTabSize = false;
if (isReservedIdToIndent(child) && startNewlineInDefinition && !startOfNewDefinition) {
if (typeExistsFor(child, HS_WHERE)) {
if (indentCounter > 0) {
indentCounter--;
}
if (haskellSettings.INDENT_WHERE_WITH_TAB_SIZE) {
indentWithTabSize = true;
} else {
indentCounter += 1;
}
} else {
indentCounter += 1;
}
alignment = null;
notIndentAgain = false;
} else if (isReservedIdToBackIndent(child) && startNewlineInDefinition) {
if (indentCounter > 0) {
indentCounter -= 1;
} else {
indentCounter = 0;
}
alignment = null;
notIndentAgain = false;
} else if (isReservedOpToIndent(child) && startNewlineInDefinition && !notIndentAgain) {
indentCounter += 1;
notIndentAgain = true;
} else if (prevNode != null) {
if (typeExistsFor(prevNode, HS_EQUAL) && startNewlineInDefinition) {
indentCounter += 1;
alignment = Alignment.createAlignment(true);
notIndentAgain = false;
} else if (indentBecausePrevReservedId(prevNode) && !startOfNewDefinition && startNewlineInDefinition) {
indentCounter += 1;
alignment = Alignment.createAlignment(true);
notIndentAgain = false;
} else if ((prevNode.getElementType() == HS_LEFT_PAREN) && startNewlineInDefinition) {
indentCounter += 1;
alignment = Alignment.createAlignment(true);
notIndentAgain = false;
}
}
blocks.add(new HaskellFormattingBlock(child, settings, haskellSettings, spacingBuilder, getWrap(), indentCounter, indentWithTabSize, alignment));
startOfNewDefinition = false;
startNewlineInDefinition = false;
prevNode = child;
}
return Collections.unmodifiableList(blocks);
}
private boolean isReservedOpToIndent(ASTNode node) {
return node.findChildByType(ReservedIdsToIndent) != null;
}
private boolean isReservedIdToIndent(ASTNode node) {
return node.findChildByType(RESERVED_IDS_TO_INDENT) != null;
}
private boolean isReservedIdToBackIndent(ASTNode node) {
return node.findChildByType(RESERVED_IDS_TO_BACK_INDENT) != null;
}
private boolean indentBecausePrevReservedId(ASTNode node) {
return node.findChildByType(INDENT_PREV_RESERVED_IDS) != null;
}
private boolean typeExistsFor(ASTNode node, IElementType elementType) {
return node.findChildByType(elementType) != null;
}
private int getTabSize() {
return settings.getIndentOptions().TAB_SIZE;
}
private int getIndentSize() {
return settings.getIndentOptions().INDENT_SIZE;
}
@Override
@Nullable
public Indent getIndent() {
return Indent.getSpaceIndent(indentCounter * getIndentSize() + (indentWithTabSize ? getTabSize() : 0));
}
@Nullable
@Override
public Wrap getWrap() {
return wrap;
}
@Nullable
@Override
public Alignment getAlignment() {
return alignment;
}
@Nullable
@Override
public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) {
return spacingBuilder.getSpacing(this, child1, child2);
}
@NotNull
@Override
public ChildAttributes getChildAttributes(int newChildIndex) {
Block block = getSubBlocks().get(newChildIndex - 1);
return new ChildAttributes(block.getIndent(), block.getAlignment());
}
@Override
public boolean isIncomplete() {
if (incomplete == null) {
incomplete = FormatterUtil.isIncomplete(getNode());
}
return incomplete;
}
@Override
public boolean isLeaf() {
return true;
}
@Override
public String toString() {
return node.getText() + " " + getTextRange();
}
}

View File

@ -0,0 +1,62 @@
/*
* Copyright 2014 Rik van der Kleij
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.powertuple.intellij.haskell.formatter;
import com.intellij.formatting.*;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.powertuple.intellij.haskell.HaskellLanguage;
import com.powertuple.intellij.haskell.HaskellParserDefinition;
import com.powertuple.intellij.haskell.formatter.settings.HaskellCodeStyleSettings;
import com.powertuple.intellij.haskell.psi.HaskellElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import static com.powertuple.intellij.haskell.psi.HaskellTypes.HS_COMMA;
import static com.powertuple.intellij.haskell.psi.HaskellTypes.HS_NEWLINE;
import static com.powertuple.intellij.haskell.psi.HaskellTypes.HS_TYPE;
public class HaskellFormattingModelBuilder implements FormattingModelBuilder {
@NotNull
@Override
public FormattingModel createModel(PsiElement element, CodeStyleSettings settings) {
CommonCodeStyleSettings commonSettings = settings.getCommonSettings(HaskellLanguage.INSTANCE);
HaskellCodeStyleSettings haskellSettings = settings.getCustomSettings(HaskellCodeStyleSettings.class);
SpacingBuilder spacingBuilder = createSpacingBuilder(commonSettings, haskellSettings);
HaskellFormattingBlock block = new HaskellFormattingBlock(element.getNode(), commonSettings, haskellSettings, spacingBuilder, Wrap.createWrap(WrapType.NONE, true), 0, false, null);
return FormattingModelProvider.createFormattingModelForPsiFile(element.getContainingFile(), block, settings);
}
private static SpacingBuilder createSpacingBuilder(CommonCodeStyleSettings settings, HaskellCodeStyleSettings haskellCodeStyleSettings) {
return new SpacingBuilder(settings.getRootSettings(), HaskellLanguage.INSTANCE)
.before(HS_COMMA).spaceIf(settings.SPACE_BEFORE_COMMA)
.after(HS_COMMA).spaceIf(settings.SPACE_AFTER_COMMA)
.around(HaskellParserDefinition.RESERVED_IDS).spaces(1);
}
@Nullable
@Override
public TextRange getRangeAffectingIndent(PsiFile file, int offset, ASTNode elementAtOffset) {
return null;
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright 2014 Rik van der Kleij
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.powertuple.intellij.haskell.formatter.settings;
import com.intellij.application.options.CodeStyleAbstractConfigurable;
import com.intellij.application.options.CodeStyleAbstractPanel;
import com.intellij.application.options.TabbedLanguageCodeStylePanel;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.powertuple.intellij.haskell.HaskellLanguage;
import org.jetbrains.annotations.NotNull;
public class HaskellCodeStyleConfigurable extends CodeStyleAbstractConfigurable {
public HaskellCodeStyleConfigurable(@NotNull CodeStyleSettings settings, CodeStyleSettings cloneSettings) {
super(settings, cloneSettings, "Haskell");
}
@Override
protected CodeStyleAbstractPanel createPanel(CodeStyleSettings settings) {
return new HaskellCodeStyleMainPanel(getCurrentSettings(), settings);
}
@Override
public String getHelpTopic() {
return null;
}
private static class HaskellCodeStyleMainPanel extends TabbedLanguageCodeStylePanel {
private HaskellCodeStyleMainPanel(CodeStyleSettings currentSettings, CodeStyleSettings settings) {
super(HaskellLanguage.INSTANCE, currentSettings, settings);
}
}
}

View File

@ -0,0 +1,28 @@
/*
* Copyright 2014 Rik van der Kleij
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.powertuple.intellij.haskell.formatter.settings;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CustomCodeStyleSettings;
public class HaskellCodeStyleSettings extends CustomCodeStyleSettings {
protected HaskellCodeStyleSettings(CodeStyleSettings settings) {
super("HaskellCodeStyleSettings", settings);
}
public boolean INDENT_WHERE_WITH_TAB_SIZE = true;
}

View File

@ -0,0 +1,42 @@
/*
* Copyright 2014 Rik van der Kleij
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.powertuple.intellij.haskell.formatter.settings;
import com.intellij.openapi.options.Configurable;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsProvider;
import com.intellij.psi.codeStyle.CustomCodeStyleSettings;
import org.jetbrains.annotations.NotNull;
public class HaskellCodeStyleSettingsProvider extends CodeStyleSettingsProvider {
@Override
public String getConfigurableDisplayName() {
return "Haskell";
}
@NotNull
@Override
public Configurable createSettingsPage(CodeStyleSettings settings, CodeStyleSettings originalSettings) {
return new HaskellCodeStyleConfigurable(settings, originalSettings);
}
@NotNull
@Override
public CustomCodeStyleSettings createCustomSettings(CodeStyleSettings settings) {
return new HaskellCodeStyleSettings(settings);
}
}

View File

@ -0,0 +1,104 @@
/*
* Copyright 2014 Rik van der Kleij
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.powertuple.intellij.haskell.formatter.settings;
import com.intellij.application.options.IndentOptionsEditor;
import com.intellij.lang.Language;
import com.intellij.psi.codeStyle.CodeStyleSettingsCustomizable;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider;
import com.powertuple.intellij.haskell.HaskellLanguage;
import org.jetbrains.annotations.NotNull;
public class HaskellLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSettingsProvider {
@NotNull
@Override
public Language getLanguage() {
return HaskellLanguage.INSTANCE;
}
@Override
public String getCodeSample(@NotNull SettingsType settingsType) {
if (settingsType == SettingsType.SPACING_SETTINGS) {
return SPACING_CODE_SAMPLE;
} else if (settingsType == SettingsType.WRAPPING_AND_BRACES_SETTINGS) {
return DEFAULT_CODE_SAMPLE;
} else if (settingsType == SettingsType.INDENT_SETTINGS) {
return INDENT_CODE_SAMPLE;
}
return DEFAULT_CODE_SAMPLE;
}
@Override
public IndentOptionsEditor getIndentOptionsEditor() {
return new HaskellSmartIndentOptionsEditor();
}
@Override
public CommonCodeStyleSettings getDefaultCommonSettings() {
CommonCodeStyleSettings defaultSettings = new CommonCodeStyleSettings(getLanguage());
CommonCodeStyleSettings.IndentOptions indentOptions = defaultSettings.initIndentOptions();
indentOptions.INDENT_SIZE = 4;
indentOptions.CONTINUATION_INDENT_SIZE = 8;
indentOptions.TAB_SIZE = 2;
return defaultSettings;
}
@Override
public void customizeSettings(@NotNull CodeStyleSettingsCustomizable consumer, @NotNull SettingsType settingsType) {
if (settingsType == SettingsType.SPACING_SETTINGS) {
consumer.showStandardOptions(
"SPACE_AFTER_COMMA",
"SPACE_BEFORE_COMMA"
);
// consumer.showCustomOption(HaskellCodeStyleSettings.class, "SPACE_AROUND_OPERATORS", "Operator", CodeStyleSettingsCustomizable.SPACES_AROUND_OPERATORS);
}
// else if (settingsType == SettingsType.BLANK_LINES_SETTINGS) {
// consumer.showStandardOptions("KEEP_BLANK_LINES_IN_CODE");
// }
}
private static final String SPACING_CODE_SAMPLE =
"l = [1,2,3]";
private static final String INDENT_CODE_SAMPLE =
"module SayHello\n" +
"(\n" +
"sayHello\n" +
") where\n" +
"\n" +
"sayHello :: IO ()\n" +
"sayHello = do\n" +
"name <- getLine\n" +
"putStrLn $ greeting name\n" +
"where\n" +
"greeting name = \"Hello, \" ++ name ++ \"!\"";
private static final String DEFAULT_CODE_SAMPLE =
"module Quicksort where\n" +
"\n" +
"quicksort :: (Ord t) => [t] -> [t]\n" +
"quicksort [] = []\n" +
"quicksort (x:xs) = quicksort smallerOrEqual ++ [x] ++ quicksort larger\n" +
"where smallerOrEqual = [y | y <- xs, y <= x]\n" +
"larger = [y | y <- xs, y > x]\n" +
"\n" +
"result = quicksort [1,2]";
}

View File

@ -0,0 +1,65 @@
/*
* Copyright 2014 Rik van der Kleij
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.powertuple.intellij.haskell.formatter.settings;
import com.intellij.application.options.SmartIndentOptionsEditor;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
public class HaskellSmartIndentOptionsEditor extends SmartIndentOptionsEditor {
private JCheckBox indentWhereWithTabSizeCheckBox;
protected void addComponents() {
super.addComponents();
indentWhereWithTabSizeCheckBox = new JCheckBox("Indent 'where' with tab size");
add(indentWhereWithTabSizeCheckBox, true);
}
public boolean isModified(final CodeStyleSettings settings, final CommonCodeStyleSettings.IndentOptions options) {
boolean isModified = super.isModified(settings, options);
isModified |= isFieldModified(indentWhereWithTabSizeCheckBox, getHaskellCodeStyleSettings(settings).INDENT_WHERE_WITH_TAB_SIZE);
return isModified;
}
public void apply(final CodeStyleSettings settings, final CommonCodeStyleSettings.IndentOptions options) {
super.apply(settings, options);
getHaskellCodeStyleSettings(settings).INDENT_WHERE_WITH_TAB_SIZE = indentWhereWithTabSizeCheckBox.isSelected();
}
public void reset(@NotNull final CodeStyleSettings settings, @NotNull final CommonCodeStyleSettings.IndentOptions options) {
super.reset(settings, options);
indentWhereWithTabSizeCheckBox.setSelected(getHaskellCodeStyleSettings(settings).INDENT_WHERE_WITH_TAB_SIZE);
}
public void setEnabled(final boolean enabled) {
super.setEnabled(enabled);
indentWhereWithTabSizeCheckBox.setEnabled(enabled);
}
private HaskellCodeStyleSettings getHaskellCodeStyleSettings(final CodeStyleSettings settings) {
return settings.getCustomSettings(HaskellCodeStyleSettings.class);
}
}

View File

@ -20,43 +20,38 @@
tokens = [
]
name(".*")='varide'
// name(".*")='varide'
// extends(".*")=lexeme
}
program ::= (lexeme | whitespace)*
whitespace ::= (whitestuff)+
whitestuff ::= WHITE_CHAR | COMMENT | NCOMMENT
lexeme ::= qvarid | qconid | qvarsym | qconsym | literal | special | reservedop | reservedid | specialreservedid
private whitespace ::= (whitestuff)+
private whitestuff ::= WHITE_CHAR | COMMENT | NCOMMENT | NEWLINE
private lexeme ::= qvarid | varid | qconid | conid | qconsym | consym | qvarsym | varsym | literal
| special | reservedop | reservedid | specialreservedid
literal ::= DECIMAL | HEXADECIMAL | OCTAL | FLOAT | CHARACTER_LITERAL | STRING_LITERAL
special ::= LEFT_PAREN | RIGHT_PAREN | COMMA | SEMICOLON | LEFT_BRACKET | RIGHT_BRACKET
private special ::= LEFT_PAREN | RIGHT_PAREN | COMMA | SEMICOLON | LEFT_BRACKET | RIGHT_BRACKET
| BACKQUOTE | LEFT_BRACE | RIGHT_BRACE
ascSymbolExcReservedopDash ::= EXCLAMATION_MARK | HASH | DOLLAR| PERCENTAGE | AMPERSAND | STAR
| PLUS | DOT | BACKSLASH | LT | GT | QUESTION_MARK | CARET
ascSymbolExcReservedop ::= ascSymbolExcReservedopDash | DASH
private ascSymbol ::= EXCLAMATION_MARK | HASH | DOLLAR| PERCENTAGE | AMPERSAND | STAR
| PLUS | DOT | SLASH | LT | EQUAL | GT | QUESTION_MARK | AT | BACKSLASH | CARET
| VERTICAL_BAR | TILDE | COLON | DASH
symbolExcReservedopDash ::= ascSymbolExcReservedopDash // ignoring unicode symbols
private symbol ::= ascSymbol // ignoring unicode symbols
varsym ::= (symbolExcReservedopDash (symbolExcReservedopDash | ':')*) // operator
consym ::= (':' (symbolExcReservedopDash | ':')*) // operator constructor
varsym ::= (symbol (symbol | ':')*) // operator
consym ::= (':' (symbol | ':')*) // operator constructor
varid ::= VAR_ID // variables
conid ::= CON_ID // constructors
tyvar ::= varid // type variables
tycon ::= conid // type constructors
tycls ::= conid // type classes
modid ::= (conid '.')* conid // modules
private varid ::= VAR_ID // variables and type variables
private conid ::= CON_ID // constructors, type constructors and type classes
qvarid ::= (modid '.')? varid
qconid ::= (modid '.')? conid
qtycon ::= (modid '.')? tycon
qtycls ::= (modid '.')? tycls
qvarsym ::= (modid '.')? varsym
qconsym ::= (modid '.')? consym
qvarid ::= (conid '.')+ varid
qconid ::= (conid '.')+ conid
qvarsym ::= (conid '.')+ varsym
qconsym ::= (conid '.')+ consym
reservedid ::= CASE | CLASS | DATA | DEFAULT | DERIVING | DO | ELSE
| FOREIGN | IF | IMPORT | IN | INFIX | INFIXL | INFIXR

View File

@ -84,7 +84,8 @@ public class HaskellColorSettingsPage implements ColorSettingsPage {
"-- line comment\n" +
"{- nested \n" +
"comment -}\n" +
"data Bool = True | False";
"data Bool = True | False\n" +
"let l = [1,2] ";
}
@NotNull

View File

@ -18,16 +18,18 @@ package com.powertuple.intellij.haskell.highlighter;
import com.intellij.lexer.Lexer;
import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
import com.intellij.openapi.editor.colors.CodeInsightColors;
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.psi.tree.TokenSet;
import com.powertuple.intellij.haskell.HaskellLexer;
import com.powertuple.intellij.haskell.HaskellParserDefinition;
import org.jetbrains.annotations.NotNull;
import static com.intellij.openapi.editor.colors.TextAttributesKey.createTextAttributesKey;
import static com.powertuple.intellij.haskell.HaskellParserDefinition.OPERATORS;
import static com.powertuple.intellij.haskell.HaskellParserDefinition.RESERVED_IDS;
import static com.powertuple.intellij.haskell.psi.HaskellTypes.*;
public class HaskellSyntaxHighlighter extends SyntaxHighlighterBase {
@ -41,20 +43,7 @@ public class HaskellSyntaxHighlighter extends SyntaxHighlighterBase {
public static final TextAttributesKey BRACE = createTextAttributesKey("HSL_BRACE", DefaultLanguageHighlighterColors.BRACES);
public static final TextAttributesKey BRACKET = createTextAttributesKey("HS_BRACKET", DefaultLanguageHighlighterColors.BRACKETS);
public static final TextAttributesKey SYMBOL = createTextAttributesKey("HS_SYMBOL", DefaultLanguageHighlighterColors.IDENTIFIER);
public static final TextAttributesKey CONSTRUCTOR = createTextAttributesKey("HS_CONSTRUCTOR", DefaultLanguageHighlighterColors.FUNCTION_DECLARATION);
private static final TokenSet RESERVED_IDS = TokenSet.create(
HS_CASE, HS_CLASS, HS_DATA, HS_DEFAULT, HS_DERIVING, HS_DO, HS_ELSE, HS_FOREIGN,
HS_IF, HS_IMPORT, HS_IN, HS_INFIX, HS_INFIXL, HS_INFIXR, HS_INSTANCE, HS_LET,
HS_MODULE, HS_NEWTYPE, HS_OF, HS_THEN, HS_TYPE, HS_WHERE, HS_UNDERSCORE
);
private static final TokenSet RESERVED_OPS = TokenSet.create(
HS_DOT_DOT, HS_COLON, HS_COLON_COLON, HS_DEFINED_BY, HS_SLASH, HS_VERTICAL_BAR,
HS_LEFT_ARROW, HS_RIGHT_ARROW, HS_AT, HS_TILDE, HS_DOUBLE_RIGHT_ARROW
);
private static final TokenSet SPECIAL_RESERVED_OPS = TokenSet.create(HS_AS, HS_QUALIFIED, HS_HIDING);
public static final TextAttributesKey CONSTRUCTOR = createTextAttributesKey("HS_CONSTRUCTOR", CodeInsightColors.CONSTRUCTOR_CALL_ATTRIBUTES);
@NotNull
@Override
@ -80,7 +69,7 @@ public class HaskellSyntaxHighlighter extends SyntaxHighlighterBase {
if (RESERVED_IDS.contains(type)) {
return pack(KEYWORD);
}
if (RESERVED_OPS.contains(type) || SPECIAL_RESERVED_OPS.contains(type)) {
if (OPERATORS.contains(type)) {
return pack(OPERATOR);
}
if (type == HS_LEFT_PAREN || type == HS_RIGHT_PAREN) {

View File

@ -27,36 +27,14 @@ import org.jetbrains.annotations.NotNull;
)
public class HaskellSettings implements PersistentStateComponent<HaskellSettings.HaskellSettingsState> {
private HaskellSettingsState haskellSettingsState = new HaskellSettingsState();
@NotNull
public static HaskellSettings getInstance() {
HaskellSettings persisted = ServiceManager.getService(HaskellSettings.class);
if (persisted == null) {
persisted = new HaskellSettings();
}
if (persisted.getState().ghcModPath == null) {
persisted.getState().ghcModPath = "ghc-mod";
}
if (persisted.getState().ghcModiPath == null) {
persisted.getState().ghcModiPath = "ghc-modi";
}
if (persisted.getState().hdocsPath == null) {
persisted.getState().hdocsPath = "hdocs";
}
return persisted;
final HaskellSettings haskellSettings = ServiceManager.getService(HaskellSettings.class);
return haskellSettings != null ? haskellSettings : new HaskellSettings();
}
public static class HaskellSettingsState {
public String ghcModPath;
public String ghcModiPath;
public String hdocsPath;
}
private HaskellSettingsState haskellSettingsState = new HaskellSettingsState();
@NotNull
public HaskellSettingsState getState() {
return haskellSettingsState;
@ -65,4 +43,10 @@ public class HaskellSettings implements PersistentStateComponent<HaskellSettings
public void loadState(HaskellSettingsState haskellSettingsState) {
this.haskellSettingsState = haskellSettingsState;
}
public static class HaskellSettingsState {
public String ghcModPath = "ghc-mod";
public String ghcModiPath = "ghc-modi";
public String hdocsPath = "hdocs";
}
}

View File

@ -16,35 +16,23 @@
package com.powertuple.intellij.haskell.annotator
import org.scalatest.{BeforeAndAfterEach, GivenWhenThen, Matchers, FunSpec}
import com.intellij.execution.process.ProcessOutput
import org.scalatest.{BeforeAndAfterEach, FunSpec, GivenWhenThen, Matchers}
class GhcModExternalAnnotatorSpec extends FunSpec with Matchers with GivenWhenThen with BeforeAndAfterEach {
val ghcModExternalAnnotator = new GhcModiExternalAnnotator
val ghcModiExternalAnnotator = new GhcModiExternalAnnotator
describe("Parsing ghc-mod output") {
Given("output of ghc-mod")
val output = new ProcessOutput()
output.appendStdout("file/path/HaskellFile.hs:1:11:parse error on input\n")
output.appendStdout("file/path/HaskellFile.hs:12:5:another parse error on input")
describe("Parsing ghc-modi output") {
Given("output of ghc-modi")
val output = "file/path/HaskellFile.hs:1:11:parse error on input"
When("parsed to problem list")
val problems = ghcModExternalAnnotator.parseGhcModOutput(output)
When("parsed to ghc-modi problem")
val ghcModiProblem = ghcModiExternalAnnotator.parseGhcModiOutputLine(output)
Then("list should have size 2")
problems should have size 2
val problem1 = problems(0)
val problem2 = problems(1)
And("contain right data")
problem1.lineNr should equal(1)
problem1.columnNr should equal(11)
problem1.description should equal("parse error on input")
problem2.lineNr should equal(12)
problem2.columnNr should equal(5)
problem2.description should equal("another parse error on input")
Then("it should contain right data")
ghcModiProblem.lineNr should equal(1)
ghcModiProblem.columnNr should equal(11)
ghcModiProblem.description should equal("parse error on input")
}
describe("Determine annotation offset when compile error") {
@ -52,20 +40,20 @@ class GhcModExternalAnnotatorSpec extends FunSpec with Matchers with GivenWhenTh
val someCode =
"""
|Some Haskell code
|which does not
| which does not
|
|com pile
""".stripMargin
When("ghc-mod is executed")
val ghcModResult = GhcModResult(Seq(GhcModProblem(4, 3, "something wrong")))
val annotations = ghcModExternalAnnotator.createAnnotations(ghcModResult, someCode)
When("ghc-modi is called")
val ghcModiResult = GhcModiResult(Seq(GhcModiProblem(4, 3, "something wrong")))
val annotations = ghcModiExternalAnnotator.createAnnotations(ghcModiResult, someCode)
Then("annotation holder should contain right annotation")
annotations should have length 1
val annotation = annotations(0)
annotation.asInstanceOf[ErrorAnnotation].textRange.getStartOffset should equal(36)
annotation.asInstanceOf[ErrorAnnotation].textRange.getStartOffset should equal(38)
}
describe("Determine annotation offset when compile warning") {
@ -75,9 +63,9 @@ class GhcModExternalAnnotatorSpec extends FunSpec with Matchers with GivenWhenTh
|some code
""".stripMargin
When("ghc-mod is executed")
val ghcModResult = GhcModResult(Seq(GhcModProblem(1, 1, "Warning: some warning")))
val annotations = ghcModExternalAnnotator.createAnnotations(ghcModResult, someCode)
When("ghc-modi is executed")
val ghcModiResult = GhcModiResult(Seq(GhcModiProblem(1, 1, "Warning: some warning")))
val annotations = ghcModiExternalAnnotator.createAnnotations(ghcModiResult, someCode)
Then("annotation holder should contain right annotation")
annotations should have length 1