mirror of
https://github.com/ilyakooo0/intellij-haskell.git
synced 2024-09-11 06:45:25 +03:00
Improvements.
This commit is contained in:
parent
a96ae7b76a
commit
c41c0ae36b
@ -20,4 +20,4 @@ lazy val intellijHaskell = (project in file(".")).
|
||||
unmanagedJars in Compile += baseDirectory.value / "idea"
|
||||
)
|
||||
|
||||
ideaBuild in ThisBuild := "142.5239.7"
|
||||
ideaBuild in ThisBuild := "143.1184.17"
|
||||
|
@ -86,9 +86,6 @@ public class HaskellParser implements PsiParser, LightPsiParser {
|
||||
else if (t == HS_DOT_DOT_PARENS) {
|
||||
r = dot_dot_parens(b, 0);
|
||||
}
|
||||
else if (t == HS_DUMMY_HEADER_PRAGMA) {
|
||||
r = dummy_header_pragma(b, 0);
|
||||
}
|
||||
else if (t == HS_EXPORT) {
|
||||
r = export(b, 0);
|
||||
}
|
||||
@ -236,6 +233,9 @@ public class HaskellParser implements PsiParser, LightPsiParser {
|
||||
else if (t == HS_PARALLEL_ARRAY_TYPE) {
|
||||
r = parallel_array_type(b, 0);
|
||||
}
|
||||
else if (t == HS_PRAGMA_RECOVER) {
|
||||
r = pragma_recover(b, 0);
|
||||
}
|
||||
else if (t == HS_QCON) {
|
||||
r = qcon(b, 0);
|
||||
}
|
||||
@ -1832,35 +1832,6 @@ public class HaskellParser implements PsiParser, LightPsiParser {
|
||||
return r;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// PRAGMA_START CONID_ID? PRAGMA_END? NEWLINE
|
||||
public static boolean dummy_header_pragma(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "dummy_header_pragma")) return false;
|
||||
if (!nextTokenIs(b, HS_PRAGMA_START)) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b);
|
||||
r = consumeToken(b, HS_PRAGMA_START);
|
||||
r = r && dummy_header_pragma_1(b, l + 1);
|
||||
r = r && dummy_header_pragma_2(b, l + 1);
|
||||
r = r && consumeToken(b, HS_NEWLINE);
|
||||
exit_section_(b, m, HS_DUMMY_HEADER_PRAGMA, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
// CONID_ID?
|
||||
private static boolean dummy_header_pragma_1(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "dummy_header_pragma_1")) return false;
|
||||
consumeToken(b, HS_CONID_ID);
|
||||
return true;
|
||||
}
|
||||
|
||||
// PRAGMA_END?
|
||||
private static boolean dummy_header_pragma_2(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "dummy_header_pragma_2")) return false;
|
||||
consumeToken(b, HS_PRAGMA_END);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// export1 | export2 | export3
|
||||
public static boolean export(PsiBuilder b, int l) {
|
||||
@ -2227,7 +2198,7 @@ public class HaskellParser implements PsiParser, LightPsiParser {
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// language_pragma | options_ghc_pragma | include_pragma | haddock_pragma | ann_pragma | dummy_header_pragma
|
||||
// language_pragma | options_ghc_pragma | include_pragma | haddock_pragma | ann_pragma
|
||||
public static boolean file_header_pragma(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "file_header_pragma")) return false;
|
||||
if (!nextTokenIs(b, HS_PRAGMA_START)) return false;
|
||||
@ -2238,7 +2209,6 @@ public class HaskellParser implements PsiParser, LightPsiParser {
|
||||
if (!r) r = include_pragma(b, l + 1);
|
||||
if (!r) r = haddock_pragma(b, l + 1);
|
||||
if (!r) r = ann_pragma(b, l + 1);
|
||||
if (!r) r = dummy_header_pragma(b, l + 1);
|
||||
exit_section_(b, m, HS_FILE_HEADER_PRAGMA, r);
|
||||
return r;
|
||||
}
|
||||
@ -2456,16 +2426,16 @@ public class HaskellParser implements PsiParser, LightPsiParser {
|
||||
// PRAGMA_START onl "OPTIONS_HADDOCK" general_pragma_content PRAGMA_END
|
||||
public static boolean haddock_pragma(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "haddock_pragma")) return false;
|
||||
if (!nextTokenIs(b, HS_PRAGMA_START)) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b);
|
||||
boolean r, p;
|
||||
Marker m = enter_section_(b, l, _NONE_, "<haddock pragma>");
|
||||
r = consumeToken(b, HS_PRAGMA_START);
|
||||
r = r && onl(b, l + 1);
|
||||
r = r && consumeToken(b, "OPTIONS_HADDOCK");
|
||||
r = r && general_pragma_content(b, l + 1);
|
||||
r = r && consumeToken(b, HS_PRAGMA_END);
|
||||
exit_section_(b, m, HS_HADDOCK_PRAGMA, r);
|
||||
return r;
|
||||
p = r; // pin = 1
|
||||
r = r && report_error_(b, onl(b, l + 1));
|
||||
r = p && report_error_(b, consumeToken(b, "OPTIONS_HADDOCK")) && r;
|
||||
r = p && report_error_(b, general_pragma_content(b, l + 1)) && r;
|
||||
r = p && consumeToken(b, HS_PRAGMA_END) && r;
|
||||
exit_section_(b, l, m, HS_HADDOCK_PRAGMA, r, p, pragma_recover_parser_);
|
||||
return r || p;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
@ -2910,16 +2880,16 @@ public class HaskellParser implements PsiParser, LightPsiParser {
|
||||
// PRAGMA_START onl "INCLUDE" general_pragma_content PRAGMA_END
|
||||
public static boolean include_pragma(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "include_pragma")) return false;
|
||||
if (!nextTokenIs(b, HS_PRAGMA_START)) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b);
|
||||
boolean r, p;
|
||||
Marker m = enter_section_(b, l, _NONE_, "<include pragma>");
|
||||
r = consumeToken(b, HS_PRAGMA_START);
|
||||
r = r && onl(b, l + 1);
|
||||
r = r && consumeToken(b, "INCLUDE");
|
||||
r = r && general_pragma_content(b, l + 1);
|
||||
r = r && consumeToken(b, HS_PRAGMA_END);
|
||||
exit_section_(b, m, HS_INCLUDE_PRAGMA, r);
|
||||
return r;
|
||||
p = r; // pin = 1
|
||||
r = r && report_error_(b, onl(b, l + 1));
|
||||
r = p && report_error_(b, consumeToken(b, "INCLUDE")) && r;
|
||||
r = p && report_error_(b, general_pragma_content(b, l + 1)) && r;
|
||||
r = p && consumeToken(b, HS_PRAGMA_END) && r;
|
||||
exit_section_(b, l, m, HS_INCLUDE_PRAGMA, r, p, pragma_recover_parser_);
|
||||
return r || p;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
@ -3608,19 +3578,19 @@ public class HaskellParser implements PsiParser, LightPsiParser {
|
||||
// PRAGMA_START onl "LANGUAGE" onl qcon (onl COMMA onl qcon)* onl PRAGMA_END
|
||||
public static boolean language_pragma(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "language_pragma")) return false;
|
||||
if (!nextTokenIs(b, HS_PRAGMA_START)) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b);
|
||||
boolean r, p;
|
||||
Marker m = enter_section_(b, l, _NONE_, "<language pragma>");
|
||||
r = consumeToken(b, HS_PRAGMA_START);
|
||||
r = r && onl(b, l + 1);
|
||||
r = r && consumeToken(b, "LANGUAGE");
|
||||
r = r && onl(b, l + 1);
|
||||
r = r && qcon(b, l + 1);
|
||||
r = r && language_pragma_5(b, l + 1);
|
||||
r = r && onl(b, l + 1);
|
||||
r = r && consumeToken(b, HS_PRAGMA_END);
|
||||
exit_section_(b, m, HS_LANGUAGE_PRAGMA, r);
|
||||
return r;
|
||||
p = r; // pin = 1
|
||||
r = r && report_error_(b, onl(b, l + 1));
|
||||
r = p && report_error_(b, consumeToken(b, "LANGUAGE")) && r;
|
||||
r = p && report_error_(b, onl(b, l + 1)) && r;
|
||||
r = p && report_error_(b, qcon(b, l + 1)) && r;
|
||||
r = p && report_error_(b, language_pragma_5(b, l + 1)) && r;
|
||||
r = p && report_error_(b, onl(b, l + 1)) && r;
|
||||
r = p && consumeToken(b, HS_PRAGMA_END) && r;
|
||||
exit_section_(b, l, m, HS_LANGUAGE_PRAGMA, r, p, pragma_recover_parser_);
|
||||
return r || p;
|
||||
}
|
||||
|
||||
// (onl COMMA onl qcon)*
|
||||
@ -4166,16 +4136,16 @@ public class HaskellParser implements PsiParser, LightPsiParser {
|
||||
// PRAGMA_START onl ("OPTIONS_GHC" | "OPTIONS") general_pragma_content PRAGMA_END
|
||||
public static boolean options_ghc_pragma(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "options_ghc_pragma")) return false;
|
||||
if (!nextTokenIs(b, HS_PRAGMA_START)) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b);
|
||||
boolean r, p;
|
||||
Marker m = enter_section_(b, l, _NONE_, "<options ghc pragma>");
|
||||
r = consumeToken(b, HS_PRAGMA_START);
|
||||
r = r && onl(b, l + 1);
|
||||
r = r && options_ghc_pragma_2(b, l + 1);
|
||||
r = r && general_pragma_content(b, l + 1);
|
||||
r = r && consumeToken(b, HS_PRAGMA_END);
|
||||
exit_section_(b, m, HS_OPTIONS_GHC_PRAGMA, r);
|
||||
return r;
|
||||
p = r; // pin = 1
|
||||
r = r && report_error_(b, onl(b, l + 1));
|
||||
r = p && report_error_(b, options_ghc_pragma_2(b, l + 1)) && r;
|
||||
r = p && report_error_(b, general_pragma_content(b, l + 1)) && r;
|
||||
r = p && consumeToken(b, HS_PRAGMA_END) && r;
|
||||
exit_section_(b, l, m, HS_OPTIONS_GHC_PRAGMA, r, p, pragma_recover_parser_);
|
||||
return r || p;
|
||||
}
|
||||
|
||||
// "OPTIONS_GHC" | "OPTIONS"
|
||||
@ -4288,6 +4258,17 @@ public class HaskellParser implements PsiParser, LightPsiParser {
|
||||
return r;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// !(PRAGMA_END)
|
||||
public static boolean pragma_recover(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "pragma_recover")) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b, l, _NOT_, "<pragma recover>");
|
||||
r = !consumeToken(b, HS_PRAGMA_END);
|
||||
exit_section_(b, l, m, HS_PRAGMA_RECOVER, r, false, null);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// onl file_header? onl module_body
|
||||
static boolean program(PsiBuilder b, int l) {
|
||||
@ -6047,4 +6028,9 @@ public class HaskellParser implements PsiParser, LightPsiParser {
|
||||
return r;
|
||||
}
|
||||
|
||||
final static Parser pragma_recover_parser_ = new Parser() {
|
||||
public boolean parse(PsiBuilder b, int l) {
|
||||
return pragma_recover(b, l + 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -10,9 +10,6 @@ public interface HaskellFileHeaderPragma extends HaskellCompositeElement {
|
||||
@Nullable
|
||||
HaskellAnnPragma getAnnPragma();
|
||||
|
||||
@Nullable
|
||||
HaskellDummyHeaderPragma getDummyHeaderPragma();
|
||||
|
||||
@Nullable
|
||||
HaskellHaddockPragma getHaddockPragma();
|
||||
|
||||
|
@ -7,7 +7,7 @@ import com.intellij.psi.PsiElement;
|
||||
|
||||
public interface HaskellHaddockPragma extends HaskellCompositeElement {
|
||||
|
||||
@NotNull
|
||||
@Nullable
|
||||
HaskellGeneralPragmaContent getGeneralPragmaContent();
|
||||
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import com.intellij.psi.PsiElement;
|
||||
|
||||
public interface HaskellIncludePragma extends HaskellCompositeElement {
|
||||
|
||||
@NotNull
|
||||
@Nullable
|
||||
HaskellGeneralPragmaContent getGeneralPragmaContent();
|
||||
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import com.intellij.psi.PsiElement;
|
||||
|
||||
public interface HaskellOptionsGhcPragma extends HaskellCompositeElement {
|
||||
|
||||
@NotNull
|
||||
@Nullable
|
||||
HaskellGeneralPragmaContent getGeneralPragmaContent();
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,6 @@ import java.util.List;
|
||||
import org.jetbrains.annotations.*;
|
||||
import com.intellij.psi.PsiElement;
|
||||
|
||||
public interface HaskellDummyHeaderPragma extends HaskellCompositeElement {
|
||||
public interface HaskellPragmaRecover extends HaskellCompositeElement {
|
||||
|
||||
}
|
@ -29,7 +29,6 @@ public interface HaskellTypes {
|
||||
IElementType HS_DEPRECATED_WARN_PRAGMA = new HaskellCompositeElementType("HS_DEPRECATED_WARN_PRAGMA");
|
||||
IElementType HS_DERIVING_DECLARATION = new HaskellCompositeElementType("HS_DERIVING_DECLARATION");
|
||||
IElementType HS_DOT_DOT_PARENS = new HaskellCompositeElementType("HS_DOT_DOT_PARENS");
|
||||
IElementType HS_DUMMY_HEADER_PRAGMA = new HaskellCompositeElementType("HS_DUMMY_HEADER_PRAGMA");
|
||||
IElementType HS_EXPORT = new HaskellCompositeElementType("HS_EXPORT");
|
||||
IElementType HS_EXPORTS = new HaskellCompositeElementType("HS_EXPORTS");
|
||||
IElementType HS_EXPRESSION = new HaskellCompositeElementType("HS_EXPRESSION");
|
||||
@ -79,6 +78,7 @@ public interface HaskellTypes {
|
||||
IElementType HS_OPTIONS_GHC_PRAGMA = new HaskellCompositeElementType("HS_OPTIONS_GHC_PRAGMA");
|
||||
IElementType HS_OTHER_PRAGMA = new HaskellCompositeElementType("HS_OTHER_PRAGMA");
|
||||
IElementType HS_PARALLEL_ARRAY_TYPE = new HaskellCompositeElementType("HS_PARALLEL_ARRAY_TYPE");
|
||||
IElementType HS_PRAGMA_RECOVER = new HaskellCompositeElementType("HS_PRAGMA_RECOVER");
|
||||
IElementType HS_QCON = new HaskellCompositeElementType("HS_QCON");
|
||||
IElementType HS_QCON_ID = new HaskellCompositeElementType("HS_QCON_ID");
|
||||
IElementType HS_QCON_ID_QUALIFIER = new HaskellCompositeElementType("HS_QCON_ID_QUALIFIER");
|
||||
@ -254,9 +254,6 @@ public interface HaskellTypes {
|
||||
else if (type == HS_DOT_DOT_PARENS) {
|
||||
return new HaskellDotDotParensImpl(node);
|
||||
}
|
||||
else if (type == HS_DUMMY_HEADER_PRAGMA) {
|
||||
return new HaskellDummyHeaderPragmaImpl(node);
|
||||
}
|
||||
else if (type == HS_EXPORT) {
|
||||
return new HaskellExportImpl(node);
|
||||
}
|
||||
@ -404,6 +401,9 @@ public interface HaskellTypes {
|
||||
else if (type == HS_PARALLEL_ARRAY_TYPE) {
|
||||
return new HaskellParallelArrayTypeImpl(node);
|
||||
}
|
||||
else if (type == HS_PRAGMA_RECOVER) {
|
||||
return new HaskellPragmaRecoverImpl(node);
|
||||
}
|
||||
else if (type == HS_QCON) {
|
||||
return new HaskellQconImpl(node);
|
||||
}
|
||||
|
@ -90,10 +90,6 @@ public class HaskellVisitor extends PsiElementVisitor {
|
||||
visitCompositeElement(o);
|
||||
}
|
||||
|
||||
public void visitDummyHeaderPragma(@NotNull HaskellDummyHeaderPragma o) {
|
||||
visitCompositeElement(o);
|
||||
}
|
||||
|
||||
public void visitExport(@NotNull HaskellExport o) {
|
||||
visitCompositeElement(o);
|
||||
}
|
||||
@ -290,6 +286,10 @@ public class HaskellVisitor extends PsiElementVisitor {
|
||||
visitCompositeElement(o);
|
||||
}
|
||||
|
||||
public void visitPragmaRecover(@NotNull HaskellPragmaRecover o) {
|
||||
visitCompositeElement(o);
|
||||
}
|
||||
|
||||
public void visitQcon(@NotNull HaskellQcon o) {
|
||||
visitQVarConOpElement(o);
|
||||
}
|
||||
|
@ -27,12 +27,6 @@ public class HaskellFileHeaderPragmaImpl extends HaskellCompositeElementImpl imp
|
||||
return findChildByClass(HaskellAnnPragma.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public HaskellDummyHeaderPragma getDummyHeaderPragma() {
|
||||
return findChildByClass(HaskellDummyHeaderPragma.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public HaskellHaddockPragma getHaddockPragma() {
|
||||
|
@ -22,9 +22,9 @@ public class HaskellHaddockPragmaImpl extends HaskellCompositeElementImpl implem
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
@Nullable
|
||||
public HaskellGeneralPragmaContent getGeneralPragmaContent() {
|
||||
return findNotNullChildByClass(HaskellGeneralPragmaContent.class);
|
||||
return findChildByClass(HaskellGeneralPragmaContent.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,9 +22,9 @@ public class HaskellIncludePragmaImpl extends HaskellCompositeElementImpl implem
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
@Nullable
|
||||
public HaskellGeneralPragmaContent getGeneralPragmaContent() {
|
||||
return findNotNullChildByClass(HaskellGeneralPragmaContent.class);
|
||||
return findChildByClass(HaskellGeneralPragmaContent.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,9 +22,9 @@ public class HaskellOptionsGhcPragmaImpl extends HaskellCompositeElementImpl imp
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
@Nullable
|
||||
public HaskellGeneralPragmaContent getGeneralPragmaContent() {
|
||||
return findNotNullChildByClass(HaskellGeneralPragmaContent.class);
|
||||
return findChildByClass(HaskellGeneralPragmaContent.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -10,14 +10,14 @@ import com.intellij.psi.util.PsiTreeUtil;
|
||||
import static com.powertuple.intellij.haskell.psi.HaskellTypes.*;
|
||||
import com.powertuple.intellij.haskell.psi.*;
|
||||
|
||||
public class HaskellDummyHeaderPragmaImpl extends HaskellCompositeElementImpl implements HaskellDummyHeaderPragma {
|
||||
public class HaskellPragmaRecoverImpl extends HaskellCompositeElementImpl implements HaskellPragmaRecover {
|
||||
|
||||
public HaskellDummyHeaderPragmaImpl(ASTNode node) {
|
||||
public HaskellPragmaRecoverImpl(ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
|
||||
public void accept(@NotNull PsiElementVisitor visitor) {
|
||||
if (visitor instanceof HaskellVisitor) ((HaskellVisitor)visitor).visitDummyHeaderPragma(this);
|
||||
if (visitor instanceof HaskellVisitor) ((HaskellVisitor)visitor).visitPragmaRecover(this);
|
||||
else super.accept(visitor);
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
<p>0.95</p>
|
||||
<ul>
|
||||
<li>Support for IntelliJ 15</li>
|
||||
<li>Building project with sbt</li>
|
||||
<li>Building intellij-haskell project with sbt</li>
|
||||
</ul>
|
||||
<p>0.9</p>
|
||||
<ul>
|
||||
@ -87,7 +87,7 @@
|
||||
</change-notes>
|
||||
|
||||
<!-- please see http://confluence.jetbrains.com/display/IDEADEV/Build+Number+Ranges for description -->
|
||||
<idea-version since-build="142.0" until-build="142.9999"/>
|
||||
<idea-version since-build="142.0" until-build="143.9999"/>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<sdkType implementation="com.powertuple.intellij.haskell.sdk.HaskellSdkType"/>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="jdk" jdkName="IntelliJ IDEA Community Edition IC-142.5239.7" jdkType="IDEA JDK" />
|
||||
<orderEntry type="jdk" jdkName="IntelliJ IDEA IU-143.1184.17" jdkType="IDEA JDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="intellijHaskell" />
|
||||
</component>
|
||||
|
@ -1,4 +1,4 @@
|
||||
resolvers += Resolver.url("dancingrobot84-bintray",
|
||||
url("http://dl.bintray.com/dancingrobot84/sbt-plugins/"))(Resolver.ivyStylePatterns)
|
||||
|
||||
addSbtPlugin("com.dancingrobot84" % "sbt-idea-plugin" % "0.3.1")
|
||||
addSbtPlugin("com.dancingrobot84" % "sbt-idea-plugin" % "0.4.1")
|
||||
|
@ -46,14 +46,6 @@ octal = 0[oO]{octit}+
|
||||
|
||||
float = [-+]?([0-9]+(\\.[0-9]*)?|\\.[0-9]+)([eE][-+]?[0-9]+)?
|
||||
|
||||
pragma_start = "{-#"
|
||||
pragma_end = "#-}"
|
||||
|
||||
comment = ("--"[^\r\n]* | "\\begin{code}")
|
||||
|
||||
ncomment_start = "{-"
|
||||
ncomment_end = "-}"
|
||||
|
||||
gap = \\({white_char}|{newline})*\\
|
||||
cntrl = {large} | [@\[\\\]\^_]
|
||||
charesc = [abfnrtv\\\"\'&]
|
||||
@ -125,6 +117,15 @@ quasi_quote_end = {vertical_bar} {right_bracket}
|
||||
|
||||
shebang_line = {hash} {exclamation_mark} [^\r\n]*
|
||||
|
||||
pragma_start = "{-#"
|
||||
pragma_end = "#-}"
|
||||
|
||||
comment = {dash}{dash}
|
||||
ncomment_start = "{-"
|
||||
ncomment_end = "-}"
|
||||
|
||||
comment = ({dash}{dash}[^\r\n]* | "\\begin{code}") {newline}
|
||||
|
||||
%%
|
||||
|
||||
<TEX> {
|
||||
@ -134,7 +135,7 @@ shebang_line = {hash} {exclamation_mark} [^\r\n]*
|
||||
}
|
||||
|
||||
<NCOMMENT> {
|
||||
{ncomment_start} ({newline}| {white_char} | {vertical_bar} | {small} | {large} | {digit} | {dash})? {
|
||||
{ncomment_start} {
|
||||
commentDepth++;
|
||||
}
|
||||
|
||||
@ -160,7 +161,7 @@ shebang_line = {hash} {exclamation_mark} [^\r\n]*
|
||||
.|{white_char}|{newline} {}
|
||||
}
|
||||
|
||||
{ncomment_start} ({vertical_bar} | {newline} | {white_char} | {small} | {large} | {digit} | {dash}) {
|
||||
{ncomment_start}({white_char} | {newline} | [^#\-\}]) {
|
||||
yybegin(NCOMMENT);
|
||||
commentDepth = 0;
|
||||
commentStart = getTokenStart();
|
||||
@ -170,11 +171,11 @@ shebang_line = {hash} {exclamation_mark} [^\r\n]*
|
||||
{comment} { return HS_COMMENT; }
|
||||
{white_space} { return com.intellij.psi.TokenType.WHITE_SPACE; }
|
||||
|
||||
{ncomment_start} { return HS_NCOMMENT_START; }
|
||||
{ncomment_end} { return HS_NCOMMENT_END; }
|
||||
{pragma_start} { return HS_PRAGMA_START; }
|
||||
{pragma_end} { return HS_PRAGMA_END; }
|
||||
|
||||
{ncomment_start} { return HS_NCOMMENT_START; }
|
||||
{ncomment_end} { return HS_NCOMMENT_END; }
|
||||
|
||||
// not listed as reserved identifier but have meaning in certain context,
|
||||
// let's say specialreservedid
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -20,6 +20,7 @@ import java.util.concurrent.{Executors, TimeUnit}
|
||||
|
||||
import com.intellij.codeInsight.completion._
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.patterns.PlatformPatterns
|
||||
import com.intellij.psi.impl.source.tree.TreeUtil
|
||||
@ -29,57 +30,60 @@ import com.intellij.util.ProcessingContext
|
||||
import com.powertuple.intellij.haskell.external.{BrowseInfo, GhcMod}
|
||||
import com.powertuple.intellij.haskell.psi.HaskellTypes._
|
||||
import com.powertuple.intellij.haskell.psi._
|
||||
import com.powertuple.intellij.haskell.util.{HaskellElementCondition, LineColumnPosition}
|
||||
import com.powertuple.intellij.haskell.util.{HaskellElementCondition, LineColumnPosition, OSUtil}
|
||||
import com.powertuple.intellij.haskell.{HaskellIcons, HaskellParserDefinition}
|
||||
|
||||
import scala.annotation.tailrec
|
||||
import scala.collection.JavaConversions._
|
||||
import scala.concurrent.duration.Duration
|
||||
import scala.concurrent.{Await, ExecutionContext, Future}
|
||||
|
||||
object HaskellCompletionContributor {
|
||||
private final val ExecutorService = Executors.newCachedThreadPool()
|
||||
implicit private final val ExecContext = ExecutionContext.fromExecutorService(ExecutorService)
|
||||
}
|
||||
|
||||
class HaskellCompletionContributor extends CompletionContributor {
|
||||
|
||||
import com.powertuple.intellij.haskell.code.HaskellCompletionContributor._
|
||||
private final val ExecutorService = Executors.newCachedThreadPool()
|
||||
implicit private final val ExecContext = ExecutionContext.fromExecutorService(ExecutorService)
|
||||
|
||||
private final val ReservedIds = HaskellParserDefinition.ALL_RESERVED_IDS.getTypes.map(_.asInstanceOf[HaskellTokenType].getName).toSeq
|
||||
private final val SpecialReservedIds = Seq("forall", "safe", "unsafe")
|
||||
private final val PragmaStartEndIds = Seq("{-# ", "#-}")
|
||||
private final val PragmaStartId = "{-#"
|
||||
private final val PragmaEndId = "#-}"
|
||||
private final val PragmaStartEndIds = Seq("{-#", "#-}")
|
||||
private final val FileHeaderPragmaIds = Seq("LANGUAGE", "OPTIONS_HADDOCK", "INCLUDE", "OPTIONS", "OPTIONS_GHC", "ANN")
|
||||
private final val ModulePragmaIds = Seq("ANN", "DEPRECATED", "WARING", "INLINE", "NOINLINE", "NOTINLINE", "INLINABEL", "LINE", "RULES",
|
||||
"SPECIALIZE", "SPECIALISE", "MINIMAL", "SOURCE", "UNPACK", "NOUNPACK")
|
||||
private final val InsideImportClauses = Seq("as", "hiding", "qualified")
|
||||
private final val CommentIds = Seq("{-", "-}", "--")
|
||||
|
||||
private final val PlainPrefixElementTypes = Seq(HS_COMMENT, HS_NCOMMENT, HS_PRAGMA_START, HS_PRAGMA_END)
|
||||
|
||||
extend(CompletionType.BASIC, PlatformPatterns.psiElement(), new CompletionProvider[CompletionParameters] {
|
||||
def addCompletions(parameters: CompletionParameters, context: ProcessingContext, originalResultSet: CompletionResultSet) {
|
||||
val project = parameters.getPosition.getProject
|
||||
val file = parameters.getOriginalFile
|
||||
|
||||
val resultSet = getNonEmptyElement(parameters.getOriginalPosition).orElse(getNonEmptyElement(parameters.getPosition)) match {
|
||||
case Some(e) if PlainPrefixElementTypes.contains(e.getNode.getElementType) | e.getText.startsWith("{") | e.getText.startsWith("#") | e.getText.startsWith("-") => originalResultSet.withPrefixMatcher(new PlainPrefixMatcher(getTextAtCaret(parameters.getEditor, file)))
|
||||
case Some(e) if e.getNode.getElementType == HS_CONID_ID && getTextAtCaret(parameters.getEditor, file).endsWith(".") => originalResultSet.withPrefixMatcher(new PlainPrefixMatcher(getTextAtCaret(parameters.getEditor, file)))
|
||||
case _ => originalResultSet
|
||||
}
|
||||
|
||||
val completionPosition = Option(parameters.getOriginalPosition).orElse(Option(parameters.getPosition))
|
||||
completionPosition match {
|
||||
case Some(p) if isPragmaInProgress(p) =>
|
||||
resultSet.addAllElements(getModulePragmaIds)
|
||||
resultSet.addAllElements(getPragmaStartEndIds)
|
||||
case Some(p) if isFileHeaderPragmaInProgress(p) =>
|
||||
resultSet.addAllElements(getLanguageExtensions(project).toSeq)
|
||||
resultSet.addAllElements(getPragmaStartEndIds)
|
||||
resultSet.addAllElements(getFileHeaderPragmaIds)
|
||||
case Some(p) if isImportSpecInProgress(p) =>
|
||||
resultSet.addAllElements(findIdsForInImportModuleSpec(project, p).toSeq)
|
||||
case Some(p) if isImportModuleDeclarationInProgress(p) =>
|
||||
resultSet.addAllElements(findModulesToImport(project).toSeq)
|
||||
resultSet.addAllElements(getInsideImportClauses)
|
||||
case Some(p) if isFileHeaderPragmaInProgress(p) =>
|
||||
resultSet.addAllElements(getLanguageExtensions(project).toSeq)
|
||||
resultSet.addAllElements(getPragmaStartEndIds)
|
||||
resultSet.addAllElements(getFileHeaderPragmaIds)
|
||||
case Some(p) if isNCommentInProgress(p) =>
|
||||
resultSet.addAllElements(getPragmaStartEndIds)
|
||||
resultSet.addAllElements(getCommentIds)
|
||||
case Some(p) if isPragmaInProgress(p) =>
|
||||
resultSet.addAllElements(getModulePragmaIds)
|
||||
resultSet.addAllElements(getPragmaStartEndIds)
|
||||
case Some(p) =>
|
||||
val importDeclarations = findImportDeclarations(file)
|
||||
getQualifiedIdentifierInProgress(p) match {
|
||||
@ -116,11 +120,33 @@ class HaskellCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
|
||||
caretElement match {
|
||||
case Some(e) if e.getText.trim.length > 0 => context.setDummyIdentifier(e.getText.trim)
|
||||
case Some(e) if e.getNode.getElementType == HS_CONID_ID && Option(e.getNextSibling).map(_.getNode.getElementType == HS_DOT).isDefined =>
|
||||
context.setDummyIdentifier(file.findElementAt(e.getTextOffset - 1).getText + ".")
|
||||
case Some(e) if PlainPrefixElementTypes.contains(e.getNode.getElementType) => context.setDummyIdentifier(getTextAtCaret(context.getEditor, file))
|
||||
case Some(e) if e.getText.trim.nonEmpty => context.setDummyIdentifier(e.getText.trim)
|
||||
case _ => context.setDummyIdentifier("a")
|
||||
}
|
||||
}
|
||||
|
||||
private def getTextAtCaret(editor: Editor, file: PsiFile): String = {
|
||||
val caretOffset = editor.getCaretModel.getOffset
|
||||
getTextUntilNoChar(file.getText, if (caretOffset > 0) caretOffset - 1 else caretOffset, "")
|
||||
}
|
||||
|
||||
@tailrec
|
||||
private def getTextUntilNoChar(fileText: String, offset: Int, text: String): String = {
|
||||
val c = fileText.charAt(offset)
|
||||
if (c < ' ' || c == OSUtil.LineSeparator || c == '\r') {
|
||||
text
|
||||
} else {
|
||||
if (offset > 0) {
|
||||
getTextUntilNoChar(fileText, offset - 1, c.toString + text)
|
||||
} else {
|
||||
c.toString + text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private def getNonEmptyElement(element: PsiElement) = {
|
||||
Option(element) match {
|
||||
case Some(s) if !s.getText.trim.isEmpty => Some(s)
|
||||
@ -130,8 +156,8 @@ class HaskellCompletionContributor extends CompletionContributor {
|
||||
|
||||
private def isImportSpecInProgress(position: PsiElement): Boolean = {
|
||||
Option(TreeUtil.findParent(position.getNode, HS_IMPORT_ID)).isDefined ||
|
||||
(Option(TreeUtil.findParent(position.getNode, HS_IMPORT_SPEC)).isDefined &&
|
||||
Option(TreeUtil.findSiblingBackward(position.getNode, HS_LEFT_PAREN)).isDefined)
|
||||
(Option(TreeUtil.findParent(position.getNode, HS_IMPORT_SPEC)).isDefined &&
|
||||
Option(TreeUtil.findSiblingBackward(position.getNode, HS_LEFT_PAREN)).isDefined)
|
||||
}
|
||||
|
||||
private def findIdsForInImportModuleSpec(project: Project, position: PsiElement) = {
|
||||
@ -143,7 +169,7 @@ class HaskellCompletionContributor extends CompletionContributor {
|
||||
|
||||
private def isImportModuleDeclarationInProgress(position: PsiElement): Boolean = {
|
||||
Option(TreeUtil.findSiblingBackward(position.getNode, HS_IMPORT)).
|
||||
orElse(Option(TreeUtil.findParent(position.getNode, HS_IMPORT_DECLARATION))).isDefined
|
||||
orElse(Option(TreeUtil.findParent(position.getNode, HS_IMPORT_DECLARATION))).isDefined
|
||||
}
|
||||
|
||||
private def findModulesToImport(project: Project) = {
|
||||
@ -156,8 +182,8 @@ class HaskellCompletionContributor extends CompletionContributor {
|
||||
|
||||
private def isFileHeaderPragmaInProgress(position: PsiElement): Boolean = {
|
||||
Option(TreeUtil.findParent(position.getNode, HaskellTypes.HS_FILE_HEADER_PRAGMA)).isDefined ||
|
||||
Option(TreeUtil.findSiblingBackward(position.getNode, HS_COMMA)).isDefined &&
|
||||
Option(TreeUtil.findSibling(position.getNode, HS_PRAGMA_END)).isDefined
|
||||
Option(TreeUtil.findSiblingBackward(position.getNode, HS_COMMA)).isDefined &&
|
||||
Option(TreeUtil.findSibling(position.getNode, HS_PRAGMA_END)).isDefined
|
||||
}
|
||||
|
||||
private def isPragmaInProgress(position: PsiElement): Boolean = {
|
||||
@ -166,25 +192,23 @@ class HaskellCompletionContributor extends CompletionContributor {
|
||||
|
||||
private def getQualifiedIdentifierInProgress(position: PsiElement): Option[String] = {
|
||||
val qualifiedElement = Option(PsiTreeUtil.findFirstParent(position, HaskellElementCondition.QualifiedElementCondition))
|
||||
qualifiedElement match {
|
||||
case Some(e: HaskellQvarId) => Some(e.getQualifier.getName)
|
||||
case Some(e: HaskellQconId) => Some(e.getQconIdQualifier.getText)
|
||||
case Some(e: HaskellQvarSym) => Some(e.getQualifier.getName)
|
||||
case Some(e: HaskellQconSym) => Some(e.getQualifier.getName)
|
||||
case _ =>
|
||||
val elementType = position.getNode.getElementType
|
||||
if (elementType == HS_NEWLINE || elementType == TokenType.WHITE_SPACE || elementType == HS_DOT) {
|
||||
Option(position.getPrevSibling).flatMap(ps => {
|
||||
val qcon = Option(PsiTreeUtil.findChildOfType(ps, classOf[HaskellQcon]))
|
||||
if (qcon.exists(qcon => Option(TreeUtil.findLastLeaf(qcon.getNextSibling.getNode)).exists(_.getElementType == HS_DOT))) {
|
||||
qcon.map(_.getName)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
qualifiedElement.map(qe => {
|
||||
qe match {
|
||||
case qe: HaskellQvarId => qe.getQualifier.getName
|
||||
case qe: HaskellQconId => qe.getQconIdQualifier.getText
|
||||
case qe: HaskellQvarSym => qe.getQualifier.getName
|
||||
case qe: HaskellQconSym => qe.getQualifier.getName
|
||||
}
|
||||
}).orElse {
|
||||
val elementType = position.getNode.getElementType
|
||||
if (elementType == HS_NEWLINE || elementType == TokenType.WHITE_SPACE || elementType == HS_DOT) {
|
||||
Option(position.getPrevSibling).flatMap(ps => {
|
||||
val qcon = Option(PsiTreeUtil.findChildOfType(ps, classOf[HaskellQcon]))
|
||||
qcon.filter(qc => Option(qc.getNextSibling).map(_.getNode).flatMap(n => Option(TreeUtil.findLastLeaf(n))).exists(_.getElementType == HS_DOT)).map(_.getName)
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -200,6 +224,10 @@ class HaskellCompletionContributor extends CompletionContributor {
|
||||
PragmaStartEndIds.map(p => LookupElementBuilder.create(p).withIcon(HaskellIcons.HaskellSmallBlueLogo).withTailText(" pragma", true))
|
||||
}
|
||||
|
||||
private def getPragmaStartId = {
|
||||
LookupElementBuilder.create(PragmaStartId).withIcon(HaskellIcons.HaskellSmallBlueLogo).withTailText(" pragma", true)
|
||||
}
|
||||
|
||||
private def getFileHeaderPragmaIds = {
|
||||
FileHeaderPragmaIds.map(p => LookupElementBuilder.create(p).withIcon(HaskellIcons.HaskellSmallBlueLogo).withTailText(" pragma", true))
|
||||
}
|
||||
@ -214,7 +242,7 @@ class HaskellCompletionContributor extends CompletionContributor {
|
||||
|
||||
private def getImportedModulesWithFullScope(psiFile: PsiFile, importDeclarations: Iterable[HaskellImportDeclaration]): Iterable[ImportFullSpec] = {
|
||||
val moduleNames = importDeclarations.filter(i => Option(i.getImportSpec).isEmpty).
|
||||
map(i => ImportFullSpec(i.getModuleName, Option(i.getImportQualified).isDefined, Option(i.getImportQualifiedAs).map(_.getQualifier).map(_.getName)))
|
||||
map(i => ImportFullSpec(i.getModuleName, Option(i.getImportQualified).isDefined, Option(i.getImportQualifiedAs).map(_.getQualifier).map(_.getName)))
|
||||
if (importDeclarations.exists(_.getModuleName == "Prelude")) {
|
||||
moduleNames
|
||||
} else {
|
||||
@ -250,9 +278,9 @@ class HaskellCompletionContributor extends CompletionContributor {
|
||||
val importFullSpecs = getImportedModulesWithFullScope(file, importDeclarations).toSeq
|
||||
|
||||
val browseInfosWithImportSpecFutures = importFullSpecs.
|
||||
map(ifs => Future {
|
||||
BrowseInfosForImportFullSpec(ifs, GhcMod.browseInfo(project, ifs.moduleName, removeParensFromOperator = true))
|
||||
}.map(bifs => createLookupElements(bifs.importSpec, bifs.browseInfos, qualifier)))
|
||||
map(ifs => Future {
|
||||
BrowseInfosForImportFullSpec(ifs, GhcMod.browseInfo(project, ifs.moduleName, removeParensFromOperator = true))
|
||||
}.map(bi => createLookupElements(bi.importSpec, bi.browseInfos, qualifier)))
|
||||
|
||||
Await.result(Future.sequence(browseInfosWithImportSpecFutures), Duration.create(5, TimeUnit.SECONDS)).flatten
|
||||
}
|
||||
@ -261,9 +289,9 @@ class HaskellCompletionContributor extends CompletionContributor {
|
||||
val importHidingIdsSpec = getImportedModulesWithHidingIdsSpec(file, importDeclarations).toSeq
|
||||
|
||||
val browseInfosWithImportHidingIdsSpecFutures = importHidingIdsSpec.
|
||||
map(ihis => Future {
|
||||
BrowseInfosForImportHidingIdsSpec(ihis, GhcMod.browseInfo(project, ihis.moduleName, removeParensFromOperator = true))
|
||||
}.map(bihis => createLookupElements(bihis.importSpec, bihis.browseInfos.filterNot(bi => bihis.importSpec.ids.contains(bi.name)), None)))
|
||||
map(bi => Future {
|
||||
BrowseInfosForImportHidingIdsSpec(bi, GhcMod.browseInfo(project, bi.moduleName, removeParensFromOperator = true))
|
||||
}.map(bis => createLookupElements(bis.importSpec, bis.browseInfos.filterNot(bi => bis.importSpec.ids.contains(bi.name)), None)))
|
||||
|
||||
Await.result(Future.sequence(browseInfosWithImportHidingIdsSpecFutures), Duration.create(5, TimeUnit.SECONDS)).flatten
|
||||
}
|
||||
@ -272,9 +300,9 @@ class HaskellCompletionContributor extends CompletionContributor {
|
||||
val importIdsSpec = getImportedModulesWithSpecIds(file, importDeclarations).toSeq
|
||||
|
||||
val browseInfosWithImportIdsSpecFutures = importIdsSpec.
|
||||
map(iis => Future {
|
||||
BrowseInfosForImportIdsSpec(iis, GhcMod.browseInfo(project, iis.moduleName, removeParensFromOperator = true))
|
||||
}.map(biis => createLookupElements(biis.importSpec, biis.browseInfos.filter(bi => biis.importSpec.ids.contains(bi.name)), qualifier)))
|
||||
map(iis => Future {
|
||||
BrowseInfosForImportIdsSpec(iis, GhcMod.browseInfo(project, iis.moduleName, removeParensFromOperator = true))
|
||||
}.map(bis => createLookupElements(bis.importSpec, bis.browseInfos.filter(bi => bis.importSpec.ids.contains(bi.name)), qualifier)))
|
||||
|
||||
Await.result(Future.sequence(browseInfosWithImportIdsSpecFutures), Duration.create(5, TimeUnit.SECONDS)).flatten
|
||||
}
|
||||
|
@ -40,15 +40,15 @@
|
||||
mixin("first_line_expression|line_expression|last_line_expression")="com.powertuple.intellij.haskell.psi.impl.HaskellLineExpressionElementImpl"
|
||||
}
|
||||
|
||||
program ::= onl file_header? onl module_body
|
||||
program ::= onl SHEBANG_LINE? onl file_header? onl module_body
|
||||
|
||||
file_header ::= SHEBANG_LINE? onl (file_header_pragma onl)+
|
||||
file_header ::= (file_header_pragma onl)+
|
||||
file_header_pragma ::= language_pragma | options_ghc_pragma | include_pragma | haddock_pragma | ann_pragma | dummy_header_pragma
|
||||
language_pragma ::= PRAGMA_START onl "LANGUAGE" onl qcon (onl COMMA onl qcon)* onl PRAGMA_END
|
||||
options_ghc_pragma ::= PRAGMA_START onl ("OPTIONS_GHC" | "OPTIONS") general_pragma_content PRAGMA_END
|
||||
include_pragma ::= PRAGMA_START onl "INCLUDE" general_pragma_content PRAGMA_END
|
||||
haddock_pragma ::= PRAGMA_START onl "OPTIONS_HADDOCK" general_pragma_content PRAGMA_END
|
||||
dummy_header_pragma ::= PRAGMA_START CONID_ID? PRAGMA_END? NEWLINE
|
||||
language_pragma ::= PRAGMA_START onl "LANGUAGE" onl qcon (onl COMMA onl qcon)* onl PRAGMA_END NEWLINE?
|
||||
options_ghc_pragma ::= PRAGMA_START onl ("OPTIONS_GHC" | "OPTIONS") general_pragma_content PRAGMA_END NEWLINE?
|
||||
include_pragma ::= PRAGMA_START onl "INCLUDE" general_pragma_content PRAGMA_END NEWLINE?
|
||||
haddock_pragma ::= PRAGMA_START onl "OPTIONS_HADDOCK" general_pragma_content PRAGMA_END NEWLINE?
|
||||
dummy_header_pragma ::= PRAGMA_START CONID_ID? PRAGMA_END? NEWLINE?
|
||||
|
||||
other_pragma ::= ann_pragma | deprecated_warn_pragma | noinline_pragma | inlinable_pragma | line_pragma | rules_pragma |
|
||||
specialize_pragma | inline_pragma | minimal_pragma
|
||||
|
@ -18,8 +18,7 @@ package com.powertuple.intellij.haskell.highlighter
|
||||
|
||||
import com.intellij.lang.{BracePair, PairedBraceMatcher}
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.tree.{TokenSet, IElementType}
|
||||
import com.powertuple.intellij.haskell.HaskellParserDefinition
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import com.powertuple.intellij.haskell.psi.HaskellTypes
|
||||
|
||||
object HaskellBraceMatcher {
|
||||
|
Loading…
Reference in New Issue
Block a user