getKey()
13 | {
14 | return KEY;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/schemely/psi/resolve/SchemeResolveResult.java:
--------------------------------------------------------------------------------
1 | package schemely.psi.resolve;
2 |
3 | import com.intellij.psi.PsiNamedElement;
4 |
5 |
6 | public class SchemeResolveResult implements com.intellij.psi.ResolveResult
7 | {
8 | private final PsiNamedElement element;
9 |
10 | public SchemeResolveResult(PsiNamedElement element)
11 | {
12 | this.element = element;
13 | }
14 |
15 | public PsiNamedElement getElement()
16 | {
17 | return element;
18 | }
19 |
20 | public boolean isValidResult()
21 | {
22 | return true;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/schemely/psi/resolve/completion/CompletionProcessor.java:
--------------------------------------------------------------------------------
1 | package schemely.psi.resolve.completion;
2 |
3 | import com.intellij.psi.PsiElement;
4 | import com.intellij.psi.ResolveState;
5 | import schemely.psi.resolve.processors.SymbolResolveProcessor;
6 |
7 |
8 | public class CompletionProcessor extends SymbolResolveProcessor
9 | {
10 | public CompletionProcessor()
11 | {
12 | super(null);
13 | }
14 |
15 | public boolean execute(PsiElement element, ResolveState state)
16 | {
17 | super.execute(element, state);
18 | return true;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/schemely/scheme/kawa/impl/KawaREPLMain.java:
--------------------------------------------------------------------------------
1 | package schemely.scheme.kawa.impl;
2 |
3 | import gnu.expr.Language;
4 | import kawa.Shell;
5 | import kawa.standard.Scheme;
6 |
7 | /**
8 | * @author Colin Fleming
9 | */
10 | public class KawaREPLMain
11 | {
12 | public static void main(String[] args)
13 | {
14 | Scheme scheme = new Scheme();
15 | Language.setCurrentLanguage(scheme);
16 | Language.setDefaults(scheme);
17 | boolean ok = Shell.run(scheme, scheme.getEnvironment());
18 | if (!ok)
19 | {
20 | System.exit(-1);
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/schemely/formatter/codeStyle/SchemeCodeStyleSettings.java:
--------------------------------------------------------------------------------
1 | package schemely.formatter.codeStyle;
2 |
3 | import com.intellij.psi.codeStyle.CodeStyleSettings;
4 | import com.intellij.psi.codeStyle.CustomCodeStyleSettings;
5 |
6 | import javax.swing.*;
7 |
8 |
9 | public class SchemeCodeStyleSettings extends CustomCodeStyleSettings
10 | {
11 | public String defineForms = "lambda\ndefine\nlet\nletrec\nlet*\ndefine-syntax\nlet-syntax\nletrec-syntax";
12 |
13 | protected SchemeCodeStyleSettings(CodeStyleSettings container)
14 | {
15 | super("SchemeCodeStyleSettings", container);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/schemely/scheme/Scheme.java:
--------------------------------------------------------------------------------
1 | package schemely.scheme;
2 |
3 | import com.intellij.lang.PsiParser;
4 | import com.intellij.lexer.Lexer;
5 | import schemely.parser.SchemePsiCreator;
6 | import schemely.repl.REPLProvider;
7 |
8 | /**
9 | * @author Colin Fleming
10 | */
11 | public interface Scheme
12 | {
13 | // Parsing customisations
14 | Lexer getLexer();
15 |
16 | PsiParser getParser();
17 |
18 | SchemePsiCreator getPsiCreator();
19 |
20 | boolean supportsSquareBracesForLists();
21 |
22 | REPLProvider getInProcessREPLProvider();
23 |
24 | REPLProvider getExternalREPLProvider();
25 | }
26 |
--------------------------------------------------------------------------------
/src/schemely/utils/SchemeUtils.java:
--------------------------------------------------------------------------------
1 | package schemely.utils;
2 |
3 | import com.intellij.openapi.module.JavaModuleType;
4 | import com.intellij.openapi.module.Module;
5 | import com.intellij.openapi.module.ModuleType;
6 |
7 |
8 | public class SchemeUtils
9 | {
10 | public static final String SCHEME_NOTIFICATION_GROUP = "Scheme";
11 |
12 | public static boolean isSuitableModule(Module module)
13 | {
14 | if (module == null)
15 | {
16 | return false;
17 | }
18 | ModuleType type = module.getModuleType();
19 | return type instanceof JavaModuleType || "PLUGIN_MODULE".equals(type.getId());
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/schemely/psi/stubs/SchemeFileStubBuilder.java:
--------------------------------------------------------------------------------
1 | package schemely.psi.stubs;
2 |
3 | import com.intellij.psi.PsiFile;
4 | import com.intellij.psi.stubs.DefaultStubBuilder;
5 | import com.intellij.psi.stubs.StubElement;
6 | import schemely.psi.impl.SchemeFile;
7 | import schemely.psi.stubs.impl.SchemeFileStubImpl;
8 |
9 |
10 | public class SchemeFileStubBuilder extends DefaultStubBuilder
11 | {
12 | protected StubElement createStubForFile(PsiFile file)
13 | {
14 | if (file instanceof SchemeFile && false)
15 | {
16 | return new SchemeFileStubImpl((SchemeFile) file);
17 | }
18 |
19 | return super.createStubForFile(file);
20 | }
21 | }
--------------------------------------------------------------------------------
/src/dk/brics/automaton/package.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Finite-state automaton for regular expressions.
4 |
5 | This package contains a full DFA/NFA implementation with Unicode
6 | alphabet and support for all standard (and a number of non-standard)
7 | regular expression operations.
8 |
9 | The most commonly used functionality is located in the classes
10 | Automaton and
11 | RegExp .
12 |
13 | For more information, go to the package home page at
14 | http://www.brics.dk/automaton/ .
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/schemely/utils/Editors.java:
--------------------------------------------------------------------------------
1 | package schemely.utils;
2 |
3 | import com.intellij.openapi.application.ApplicationManager;
4 | import com.intellij.openapi.editor.Editor;
5 | import com.intellij.openapi.editor.ScrollType;
6 |
7 | /**
8 | * @author Colin Fleming
9 | */
10 | public class Editors
11 | {
12 | public static void scrollDown(final Editor editor)
13 | {
14 | ApplicationManager.getApplication().invokeLater(new Runnable()
15 | {
16 | @Override
17 | public void run()
18 | {
19 | editor.getCaretModel().moveToOffset(editor.getDocument().getTextLength());
20 | editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
21 | }
22 | });
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/schemely/repl/toolwindow/REPLToolWindowFactory.java:
--------------------------------------------------------------------------------
1 | package schemely.repl.toolwindow;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import com.intellij.openapi.wm.ToolWindow;
5 | import com.intellij.openapi.wm.ToolWindowFactory;
6 |
7 | import java.awt.*;
8 |
9 | /**
10 | * @author Colin Fleming
11 | */
12 | public class REPLToolWindowFactory implements ToolWindowFactory
13 | {
14 | public static final String TOOL_WINDOW_ID = "Scheme.REPL";
15 |
16 | @Override
17 | public void createToolWindowContent(Project project, ToolWindow toolWindow)
18 | {
19 | // By default tool window has no content
20 | toolWindow.setToHideOnEmptyContent(true);
21 | toolWindow.getComponent().setForeground(Color.WHITE);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/schemely/utils/SchemeNamesUtil.java:
--------------------------------------------------------------------------------
1 | package schemely.utils;
2 |
3 | import com.intellij.lexer.Lexer;
4 | import com.intellij.openapi.application.ApplicationManager;
5 | import schemely.lexer.SchemeLexer;
6 | import schemely.lexer.Tokens;
7 |
8 |
9 | public class SchemeNamesUtil
10 | {
11 | public static boolean isIdentifier(String text)
12 | {
13 | ApplicationManager.getApplication().assertReadAccessAllowed();
14 | if (text == null)
15 | {
16 | return false;
17 | }
18 | Lexer lexer = new SchemeLexer();
19 | lexer.start(text, 0, text.length(), 0);
20 | if (lexer.getTokenType() != Tokens.IDENTIFIER)
21 | {
22 | return false;
23 | }
24 | lexer.advance();
25 | return lexer.getTokenType() == null;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/schemely/psi/util/SchemeTextUtil.java:
--------------------------------------------------------------------------------
1 | package schemely.psi.util;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 |
5 |
6 | public abstract class SchemeTextUtil
7 | {
8 | public static String getLastSymbolAtom(@NotNull String sym, @NotNull String sep)
9 | {
10 | int index = sym.lastIndexOf(sep);
11 | return index > 0 && index < sym.length() - 1 ? sym.substring(index + 1) : sym;
12 | }
13 |
14 | public static String getSymbolPrefix(@NotNull String sym, @NotNull String sep)
15 | {
16 | int index = sym.lastIndexOf(sep);
17 | return index > 0 && index < sym.length() - 1 ? sym.substring(0, index) : "";
18 | }
19 |
20 | public static String getSymbolPrefix(@NotNull String sym)
21 | {
22 | return getSymbolPrefix(sym, ".");
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/schemely/SchemeIcons.java:
--------------------------------------------------------------------------------
1 | package schemely;
2 |
3 | import com.intellij.openapi.util.IconLoader;
4 | import org.jetbrains.annotations.NonNls;
5 |
6 | import javax.swing.*;
7 |
8 | public interface SchemeIcons
9 | {
10 | @NonNls
11 | final Icon SCHEME_ICON = IconLoader.findIcon("/schemely/icons/lambda.png");
12 |
13 | final Icon FUNCTION = IconLoader.findIcon("/schemely/icons/function.png");
14 | final Icon METHOD = IconLoader.findIcon("/schemely/icons/method.png");
15 | final Icon JAVA_METHOD = IconLoader.findIcon("/schemely/icons/java_method.png");
16 | final Icon JAVA_FIELD = IconLoader.findIcon("/schemely/icons/java_field.png");
17 | final Icon SYMBOL = IconLoader.findIcon("/schemely/icons/symbol.png");
18 | final Icon NAMESPACE = IconLoader.findIcon("/schemely/icons/namespace.png");
19 | }
20 |
--------------------------------------------------------------------------------
/src/schemely/formatter/codeStyle/SchemeCodeStyleSettingsProvider.java:
--------------------------------------------------------------------------------
1 | package schemely.formatter.codeStyle;
2 |
3 | import com.intellij.psi.codeStyle.CodeStyleSettingsProvider;
4 | import com.intellij.psi.codeStyle.CodeStyleSettings;
5 | import com.intellij.psi.codeStyle.CustomCodeStyleSettings;
6 | import com.intellij.openapi.options.Configurable;
7 | import org.jetbrains.annotations.NotNull;
8 |
9 |
10 | public class SchemeCodeStyleSettingsProvider extends CodeStyleSettingsProvider
11 | {
12 | @NotNull
13 | public Configurable createSettingsPage(CodeStyleSettings settings, CodeStyleSettings originalSettings)
14 | {
15 | return new SchemeFormatConfigurable(settings, originalSettings);
16 | }
17 |
18 | @Override
19 | public CustomCodeStyleSettings createCustomSettings(CodeStyleSettings settings)
20 | {
21 | return new SchemeCodeStyleSettings(settings);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/schemely/psi/resolve/processors/ResolveProcessor.java:
--------------------------------------------------------------------------------
1 | package schemely.psi.resolve.processors;
2 |
3 | import com.intellij.psi.scope.ElementClassHint;
4 | import com.intellij.psi.scope.NameHint;
5 | import com.intellij.psi.scope.PsiScopeProcessor;
6 | import com.intellij.util.containers.HashSet;
7 | import schemely.psi.resolve.SchemeResolveResult;
8 |
9 |
10 | public abstract class ResolveProcessor implements PsiScopeProcessor, NameHint, ElementClassHint
11 | {
12 | protected HashSet candidates = new HashSet();
13 | protected final String name;
14 |
15 | public ResolveProcessor(String name)
16 | {
17 | this.name = name;
18 | }
19 |
20 | public SchemeResolveResult[] getCandidates()
21 | {
22 | return candidates.toArray(new SchemeResolveResult[candidates.size()]);
23 | }
24 |
25 | public void handleEvent(Event event, Object o)
26 | {
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/schemely/psi/util/SchemePsiElementFactory.java:
--------------------------------------------------------------------------------
1 | package schemely.psi.util;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import com.intellij.openapi.components.ServiceManager;
5 | import com.intellij.lang.ASTNode;
6 | import com.intellij.psi.PsiElement;
7 | import org.jetbrains.annotations.NotNull;
8 | import schemely.psi.impl.SchemeFile;
9 |
10 |
11 | public abstract class SchemePsiElementFactory
12 | {
13 | public static SchemePsiElementFactory getInstance(Project project)
14 | {
15 | return ServiceManager.getService(project, SchemePsiElementFactory.class);
16 | }
17 |
18 | public abstract ASTNode createSymbolNodeFromText(@NotNull String newName);
19 |
20 | public abstract boolean hasSyntacticalErrors(@NotNull String text);
21 |
22 | public abstract boolean hasSyntacticalErrors(@NotNull PsiElement element);
23 |
24 | public abstract SchemeFile createSchemeFileFromText(String text);
25 | }
26 |
--------------------------------------------------------------------------------
/src/schemely/structure/SchemeStructureViewBuilderFactory.java:
--------------------------------------------------------------------------------
1 | package schemely.structure;
2 |
3 | import com.intellij.lang.PsiStructureViewFactory;
4 | import com.intellij.ide.structureView.StructureViewBuilder;
5 | import com.intellij.ide.structureView.TreeBasedStructureViewBuilder;
6 | import com.intellij.ide.structureView.StructureViewModel;
7 | import com.intellij.psi.PsiFile;
8 | import org.jetbrains.annotations.NotNull;
9 |
10 |
11 | public class SchemeStructureViewBuilderFactory implements PsiStructureViewFactory
12 | {
13 | public StructureViewBuilder getStructureViewBuilder(final PsiFile psiFile)
14 | {
15 | return new TreeBasedStructureViewBuilder()
16 | {
17 | @NotNull
18 | public StructureViewModel createStructureViewModel()
19 | {
20 | return new SchemeStructureViewModel(psiFile);
21 | }
22 |
23 | public boolean isRootNodeShown()
24 | {
25 | return false;
26 | }
27 | };
28 | }
29 | }
--------------------------------------------------------------------------------
/todo.txt:
--------------------------------------------------------------------------------
1 | * Symbol completion
2 | - Add symbols from r5rs, Kawa, SISC etc. (stub generation, include in plugin?)
3 | - Investigate doc for symbols
4 |
5 | * Structure view & completion should show function parameters
6 |
7 | * More binding forms - syntax-rules
8 |
9 | * Better AST?
10 |
11 | * Macro resolution
12 |
13 | * Customisable indentation - how to create scheme editor in code style panel?
14 |
15 | * Customisable list of keyword names
16 |
17 | * Compiler - check for SDK, use built in if not, warn
18 |
19 | * Remove Facet
20 |
21 | * Runner creation
22 |
23 | * Scheme Implementation
24 | - Symbol resolution (identifier, file)
25 | - Completion symbols
26 | - Compiler (SchemeBackendCompiler)
27 | - REPL (Classpath, Prompt, ProcessHandler, Console highlighting, Console detection)
28 | - Annotation list?
29 |
30 | * Allow case-sensitivity
31 |
32 | * Internationalise
33 |
34 | * Fix highlighting w/quoting of lists
35 |
36 | * REPL
37 | - prefix output
38 | - investigate
39 |
--------------------------------------------------------------------------------
/src/schemely/psi/impl/SchemeQuoted.java:
--------------------------------------------------------------------------------
1 | package schemely.psi.impl;
2 |
3 | import com.intellij.lang.ASTNode;
4 | import com.intellij.psi.tree.IElementType;
5 | import schemely.lexer.Tokens;
6 |
7 |
8 | public class SchemeQuoted extends SchemePsiElementBase
9 | {
10 | public SchemeQuoted(ASTNode node)
11 | {
12 | super(node, "Quoted");
13 | }
14 |
15 | @Override
16 | public String toString()
17 | {
18 | return "SchemeQuoted";
19 | }
20 |
21 | @Override
22 | public int getQuotingLevel()
23 | {
24 | ASTNode child = getNode().findChildByType(Tokens.PREFIXES);
25 | if (child != null)
26 | {
27 | IElementType type = child.getElementType();
28 | if ((type == Tokens.QUOTE_MARK) || (type == Tokens.BACKQUOTE))
29 | {
30 | return 1;
31 | }
32 | else if (type == Tokens.COMMA || type == Tokens.COMMA_AT)
33 | {
34 | return -1;
35 | }
36 | }
37 |
38 | // Should never happen
39 | return 0;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/schemely/scheme/SchemeImplementation.java:
--------------------------------------------------------------------------------
1 | package schemely.scheme;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import schemely.scheme.kawa.KawaScheme;
5 | import schemely.scheme.sisc.SISCScheme;
6 | import schemely.settings.SchemeProjectSettings;
7 |
8 | /**
9 | * @author Colin Fleming
10 | */
11 | public enum SchemeImplementation
12 | {
13 | // KAWA_1_11("Bundled Kawa 1.11", new KawaScheme()),
14 | SISC_1_16_6("Bundled SISC 1.16.6", new SISCScheme());
15 |
16 | private final String description;
17 | private final Scheme scheme;
18 |
19 | SchemeImplementation(String description, Scheme scheme)
20 | {
21 | this.description = description;
22 | this.scheme = scheme;
23 | }
24 |
25 | @Override
26 | public String toString()
27 | {
28 | return description;
29 | }
30 |
31 | public static Scheme from(Project project)
32 | {
33 | SchemeProjectSettings settings = SchemeProjectSettings.getInstance(project);
34 | return settings.schemeImplementation.scheme;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/schemely/parser/AST.java:
--------------------------------------------------------------------------------
1 | package schemely.parser;
2 |
3 | import com.intellij.psi.tree.IElementType;
4 | import com.intellij.psi.tree.IStubFileElementType;
5 | import com.intellij.psi.tree.TokenSet;
6 | import schemely.lexer.Tokens;
7 | import schemely.psi.stubs.elements.SchemeStubFileElementType;
8 |
9 | public interface AST extends Tokens
10 | {
11 | final IStubFileElementType FILE = new SchemeStubFileElementType();
12 |
13 | final IElementType LIST = new SchemeElementType("list");
14 | final IElementType VECTOR = new SchemeElementType("vector");
15 |
16 | final IElementType LITERAL = new SchemeElementType("literal");
17 | final IElementType IDENTIFIER = new SchemeElementType("identifier");
18 | final IElementType SPECIAL = new SchemeElementType("special");
19 |
20 | final IElementType QUOTED = new SchemeElementType("abbreviation");
21 |
22 | TokenSet LIST_LIKE_FORMS = TokenSet.create(LIST, VECTOR);
23 |
24 | TokenSet BRACES = TokenSet.create(LEFT_CURLY, LEFT_PAREN, LEFT_SQUARE, RIGHT_CURLY, RIGHT_PAREN, RIGHT_SQUARE);
25 | }
26 |
--------------------------------------------------------------------------------
/src/schemely/scheme/REPL.java:
--------------------------------------------------------------------------------
1 | package schemely.scheme;
2 |
3 | import com.intellij.openapi.actionSystem.AnAction;
4 | import com.intellij.openapi.util.Key;
5 | import com.intellij.psi.PsiElement;
6 | import com.intellij.psi.PsiManager;
7 | import com.intellij.psi.PsiNamedElement;
8 | import com.intellij.ui.content.Content;
9 | import schemely.repl.SchemeConsoleView;
10 |
11 | import java.util.Collection;
12 |
13 | /**
14 | * @author Colin Fleming
15 | */
16 | public interface REPL
17 | {
18 | Key REPL_KEY = Key.create("Scheme.REPL");
19 | Key CONTENT_KEY = Key.create("Scheme.REPL.Content");
20 |
21 | void execute(String command);
22 |
23 | void start() throws REPLException;
24 |
25 | void stop() throws REPLException;
26 |
27 | boolean isActive();
28 |
29 | boolean isExecuting();
30 |
31 | SchemeConsoleView getConsoleView();
32 |
33 | // Guaranteed to be called after start()
34 | AnAction[] getToolbarActions() throws REPLException;
35 |
36 | Collection getSymbolVariants(PsiManager manager, PsiElement symbol);
37 | }
38 |
--------------------------------------------------------------------------------
/src/schemely/SchemeBundle.java:
--------------------------------------------------------------------------------
1 | package schemely;
2 |
3 | import com.intellij.CommonBundle;
4 | import org.jetbrains.annotations.NonNls;
5 | import org.jetbrains.annotations.PropertyKey;
6 |
7 | import java.lang.ref.Reference;
8 | import java.lang.ref.SoftReference;
9 | import java.util.ResourceBundle;
10 |
11 |
12 | public class SchemeBundle
13 | {
14 | private static Reference ourBundle;
15 |
16 | @NonNls
17 | private static final String BUNDLE = "schemely.SchemeBundle";
18 |
19 | public static String message(@PropertyKey(resourceBundle = BUNDLE) String key, Object... params)
20 | {
21 | return CommonBundle.message(getBundle(), key, params);
22 | }
23 |
24 | private static ResourceBundle getBundle()
25 | {
26 | ResourceBundle bundle = null;
27 |
28 | if (ourBundle != null)
29 | {
30 | bundle = ourBundle.get();
31 | }
32 |
33 | if (bundle == null)
34 | {
35 | bundle = ResourceBundle.getBundle(BUNDLE);
36 | ourBundle = new SoftReference(bundle);
37 | }
38 | return bundle;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/schemely/formatter/codeStyle/SchemeFormatConfigurable.java:
--------------------------------------------------------------------------------
1 | package schemely.formatter.codeStyle;
2 |
3 | import com.intellij.application.options.CodeStyleAbstractConfigurable;
4 | import com.intellij.application.options.CodeStyleAbstractPanel;
5 | import com.intellij.psi.codeStyle.CodeStyleSettings;
6 | import schemely.SchemeBundle;
7 | import schemely.SchemeIcons;
8 |
9 | import javax.swing.*;
10 |
11 |
12 | public class SchemeFormatConfigurable extends CodeStyleAbstractConfigurable
13 | {
14 | public SchemeFormatConfigurable(CodeStyleSettings settings, CodeStyleSettings cloneSettings)
15 | {
16 | super(settings, cloneSettings, SchemeBundle.message("title.scheme.code.style.settings"));
17 | }
18 |
19 | protected CodeStyleAbstractPanel createPanel(CodeStyleSettings settings)
20 | {
21 | return new SchemeCodeStylePanel(settings);
22 | }
23 |
24 | @Override
25 | public Icon getIcon()
26 | {
27 | return SchemeIcons.SCHEME_ICON;
28 | }
29 |
30 | public String getHelpTopic()
31 | {
32 | return "reference.settingsdialog.IDE.globalcodestyle.spaces";
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/test/schemely/lexer/SISCLexerTest.java:
--------------------------------------------------------------------------------
1 | package schemely.lexer;
2 |
3 | import org.testng.annotations.DataProvider;
4 | import schemely.TestUtil;
5 | import schemely.scheme.sisc.lexer.SISCLexer;
6 | import schemely.scheme.sisc.lexer.SISCTokens;
7 |
8 | /**
9 | * @author Colin Fleming
10 | */
11 | public class SISCLexerTest extends LexerTestBase
12 | {
13 | @DataProvider(name = "lexerTests")
14 | private static Object[][] lexerTestCases()
15 | {
16 | return TestUtil.testArray(testCase("#0=", SISCTokens.PTR_DEF),
17 | testCase("#0#", SISCTokens.PTR_REF),
18 | testCase("#%let", Tokens.IDENTIFIER),
19 | testCase("#0(", Tokens.OPEN_VECTOR),
20 | testCase("#'", SISCTokens.SYNTAX_QUOTE),
21 | testCase(".token", Tokens.IDENTIFIER),
22 | testCase("|token|", Tokens.IDENTIFIER),
23 | testCase("->int", Tokens.IDENTIFIER));
24 | }
25 |
26 | @Override
27 | protected SchemeLexer getLexer()
28 | {
29 | return new SISCLexer();
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/schemely/psi/stubs/index/SchemeFullScriptNameIndex.java:
--------------------------------------------------------------------------------
1 | package schemely.psi.stubs.index;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import com.intellij.psi.search.GlobalSearchScope;
5 | import com.intellij.psi.stubs.IntStubIndexExtension;
6 | import com.intellij.psi.stubs.StubIndexKey;
7 | import schemely.psi.impl.SchemeFile;
8 | import schemely.psi.impl.search.SchemeSourceFilterScope;
9 |
10 | import java.util.Collection;
11 |
12 |
13 | public class SchemeFullScriptNameIndex extends IntStubIndexExtension
14 | {
15 | public static final StubIndexKey KEY = StubIndexKey.createIndexKey("scm.script.fqn");
16 |
17 | private static final SchemeFullScriptNameIndex ourInstance = new SchemeFullScriptNameIndex();
18 |
19 | public static SchemeFullScriptNameIndex getInstance()
20 | {
21 | return ourInstance;
22 | }
23 |
24 | public StubIndexKey getKey()
25 | {
26 | return KEY;
27 | }
28 |
29 | public Collection get(Integer integer, Project project, GlobalSearchScope scope)
30 | {
31 | return super.get(integer, project, new SchemeSourceFilterScope(scope, project));
32 | }
33 | }
--------------------------------------------------------------------------------
/src/schemely/editor/selection/SchemeLiteralSelectioner.java:
--------------------------------------------------------------------------------
1 | package schemely.editor.selection;
2 |
3 | import com.intellij.codeInsight.editorActions.ExtendWordSelectionHandler;
4 | import com.intellij.openapi.editor.Editor;
5 | import com.intellij.openapi.util.TextRange;
6 | import com.intellij.psi.PsiElement;
7 | import schemely.psi.util.SchemePsiUtil;
8 |
9 | import java.util.ArrayList;
10 | import java.util.List;
11 |
12 |
13 | public class SchemeLiteralSelectioner implements ExtendWordSelectionHandler
14 | {
15 | public boolean canSelect(PsiElement e)
16 | {
17 | PsiElement parent = e.getParent();
18 | return SchemePsiUtil.isStringLiteral(e) || SchemePsiUtil.isStringLiteral(parent);
19 | }
20 |
21 | public List select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor)
22 | {
23 | List result = new ArrayList();
24 |
25 | TextRange range = e.getTextRange();
26 | if (range.getLength() <= 2)
27 | {
28 | result.add(range);
29 | }
30 | else
31 | {
32 | result.add(new TextRange(range.getStartOffset() + 1, range.getEndOffset() - 1));
33 | }
34 | return result;
35 | }
36 | }
--------------------------------------------------------------------------------
/scheme-src/conversion.scm:
--------------------------------------------------------------------------------
1 | (define-alias StdLanguages com.intellij.lang.StdLanguages)
2 | (define-alias PsiElement com.intellij.psi.PsiElement)
3 |
4 | (define-syntax type-match
5 | (syntax-rules (else)
6 | ((type-match var (else result1 result2 ...))
7 | (begin result1 result2 ...))
8 | ((type-match var ((type new-var))) #f)
9 | ((type-match var ((type new-var)) clause1 clause2 ...)
10 | (or (instance? var type) (type-match var clause1 clause2 ...)))
11 | ((type-match var ((type new-var) result1 result2 ...))
12 | (if (instance? var type)
13 | (let ((new-var :: type (as type var))) result1 result2 ...)))
14 | ((type-match var ((type new-var) result1 result2 ...)
15 | clause1 clause2 ...)
16 | (if (instance? var type)
17 | (let ((new-var :: type (as type var))) result1 result2 ...)
18 | (type-match var clause1 clause2 ...)))))
19 |
20 | (define psi-to-text
21 | (lambda (element :: PsiElement)
22 | (cond
23 | ((eq? element #!null) "")
24 | ((not (eq? (element:get-language) StdLanguages:.JAVA)) "")
25 | (else
26 | (string-append "; Element " ((element:get-class):get-simple-name) " not supported\n")))))
27 |
--------------------------------------------------------------------------------
/src/schemely/file/SchemeFileType.java:
--------------------------------------------------------------------------------
1 | package schemely.file;
2 |
3 | import com.intellij.lang.Language;
4 | import com.intellij.openapi.fileTypes.LanguageFileType;
5 | import org.jetbrains.annotations.NonNls;
6 | import org.jetbrains.annotations.NotNull;
7 | import schemely.SchemeIcons;
8 | import schemely.SchemeLanguage;
9 |
10 | import javax.swing.Icon;
11 |
12 | public class SchemeFileType extends LanguageFileType
13 | {
14 | public static final SchemeFileType SCHEME_FILE_TYPE = new SchemeFileType();
15 | public static final Language SCHEME_LANGUAGE = SCHEME_FILE_TYPE.getLanguage();
16 | @NonNls
17 | public static final String SCHEME_EXTENSIONS = "scm;ss";
18 |
19 |
20 | public SchemeFileType()
21 | {
22 | super(new SchemeLanguage());
23 | }
24 |
25 | @NotNull
26 | public String getName()
27 | {
28 | return "Scheme";
29 | }
30 |
31 | @NotNull
32 | public String getDescription()
33 | {
34 | return "Scheme file";
35 | }
36 |
37 | @NotNull
38 | public String getDefaultExtension()
39 | {
40 | return "scm";
41 | }
42 |
43 | public Icon getIcon()
44 | {
45 | return SchemeIcons.SCHEME_ICON;
46 | }
47 |
48 | public boolean isJVMDebuggingSupported()
49 | {
50 | return true;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/schemely/scheme/sisc/SISCConfigUtil.java:
--------------------------------------------------------------------------------
1 | package schemely.scheme.sisc;
2 |
3 | import com.intellij.openapi.application.PathManager;
4 | import com.intellij.util.PathUtil;
5 | import org.jetbrains.annotations.NonNls;
6 | import sisc.REPL;
7 | import sisc.modules.Types;
8 |
9 | import java.io.File;
10 |
11 | /**
12 | * @author Colin Fleming
13 | */
14 | public class SISCConfigUtil
15 | {
16 | @NonNls
17 | public static final String SISC_JAR_NAME_PREFIX = "sisc";
18 | @NonNls
19 | public static final String SISC_MAIN_CLASS_FILE = "sisc/REPL.class";
20 | @NonNls
21 | public static final String SISC_SDK = PathUtil.getJarPathForClass(REPL.class);
22 | @NonNls
23 | public static final String SISC_LIB = getJarPathForResource(REPL.class, "sisc/libs/srfi.scc");
24 | @NonNls
25 | public static final String SISC_SRC = getJarPathForResource(REPL.class, "sisc/boot/repl.scm");
26 | @NonNls
27 | public static final String SISC_OPT = PathUtil.getJarPathForClass(Types.class);
28 |
29 | public static String getJarPathForResource(Class> aClass, String resourceName) {
30 | String resourceRoot = PathManager.getResourceRoot(aClass, '/' + resourceName);
31 | return new File(resourceRoot).getAbsoluteFile().getAbsolutePath();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/schemely/navigation/SchemeNavigationOffsetProvider.java:
--------------------------------------------------------------------------------
1 | package schemely.navigation;
2 |
3 | import com.intellij.codeInsight.navigation.MethodNavigationOffsetProvider;
4 | import com.intellij.codeInsight.navigation.MethodUpDownUtil;
5 | import com.intellij.psi.PsiElement;
6 | import com.intellij.psi.PsiFile;
7 | import schemely.psi.impl.SchemeFile;
8 | import schemely.psi.impl.list.SchemeList;
9 |
10 | import java.util.ArrayList;
11 | import java.util.List;
12 |
13 | /**
14 | * @author Colin Fleming
15 | */
16 | public class SchemeNavigationOffsetProvider implements MethodNavigationOffsetProvider
17 | {
18 | @Override
19 | public int[] getMethodNavigationOffsets(PsiFile file, int caretOffset)
20 | {
21 | if (file instanceof SchemeFile)
22 | {
23 | List array = new ArrayList();
24 | for (PsiElement element : file.getChildren())
25 | {
26 | if (element instanceof SchemeList)
27 | {
28 | PsiElement navigationItem = ((SchemeList) element).getFunctionNavigationItem();
29 | if (navigationItem != null)
30 | {
31 | array.add(navigationItem);
32 | }
33 | }
34 | }
35 | return MethodUpDownUtil.offsetsFromElements(array);
36 | }
37 | return null;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/test/schemely/parser/ParserTest.java:
--------------------------------------------------------------------------------
1 | package schemely.parser;
2 |
3 | import org.testng.annotations.DataProvider;
4 | import schemely.TestUtil;
5 | import schemely.psi.impl.SchemeQuoted;
6 | import schemely.psi.impl.SchemeVector;
7 |
8 |
9 | public class ParserTest extends ParseTestCaseBase
10 | {
11 | @DataProvider(name = "parseFiles")
12 | private Object[][] getParseFiles()
13 | {
14 | setUp();
15 | return TestUtil.testArray(identifier("foo"),
16 | identifier("foo*"),
17 | literal("123"),
18 | literal("123.123"),
19 | literal("\"123.456\""),
20 | literal("\"this is\n" + " a multiline\n" + " string\""),
21 | list("(a b)"),
22 | list("(a b (c d))"),
23 | element("'(a b (c d))", SchemeQuoted.class),
24 | element("'a", SchemeQuoted.class),
25 | element("#(a b (c d))", SchemeVector.class),
26 | list("()"),
27 | element("#()", SchemeVector.class),
28 | improperList("(a b . c)"));
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/schemely/gotoclass/SchemeGoToSymbolContributor.java:
--------------------------------------------------------------------------------
1 | package schemely.gotoclass;
2 |
3 | import com.intellij.navigation.ChooseByNameContributor;
4 | import com.intellij.navigation.NavigationItem;
5 | import com.intellij.openapi.project.Project;
6 | import com.intellij.psi.search.GlobalSearchScope;
7 |
8 | import java.util.ArrayList;
9 | import java.util.HashSet;
10 | import java.util.List;
11 | import java.util.Set;
12 |
13 |
14 | public class SchemeGoToSymbolContributor implements ChooseByNameContributor
15 | {
16 | public String[] getNames(Project project, boolean includeNonProjectItems)
17 | {
18 | Set symbols = new HashSet();
19 | // symbols.addAll(StubIndex.getInstance().getAllKeys(ClDefNameIndex.KEY));
20 | return symbols.toArray(new String[symbols.size()]);
21 |
22 | }
23 |
24 | public NavigationItem[] getItemsByName(String name, String pattern, Project project, boolean includeNonProjectItems)
25 | {
26 | GlobalSearchScope scope = includeNonProjectItems ? null : GlobalSearchScope.projectScope(project);
27 |
28 | List symbols = new ArrayList();
29 | // symbols.addAll(StubIndex.getInstance().get(ClDefNameIndex.KEY, name, project, scope));
30 | return symbols.toArray(new NavigationItem[symbols.size()]);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/test/schemely/scheme/sisc/SISCOutputProcessorTest.java:
--------------------------------------------------------------------------------
1 | package schemely.scheme.sisc;
2 |
3 | import junit.framework.TestCase;
4 |
5 | import static schemely.scheme.sisc.SISCOutputProcessor.looksLikeError;
6 |
7 | /**
8 | * @author Colin Fleming
9 | */
10 | public class SISCOutputProcessorTest extends TestCase
11 | {
12 | public void testErrors()
13 | {
14 | assertTrue(looksLikeError("Error.\n"));
15 | assertTrue(looksLikeError("Error. \n"));
16 | assertTrue(looksLikeError("Error.\t\n"));
17 | assertTrue(looksLikeError("Error in some location.\t\n"));
18 | assertTrue(looksLikeError("Error in some.location.with.periods.\t\n"));
19 | assertTrue(looksLikeError("Error: some message\n"));
20 | assertTrue(looksLikeError("Error in some location: some message\n"));
21 | assertTrue(looksLikeError("Error in nested call.\n"));
22 | assertTrue(looksLikeError("Error in nested call: some message\n"));
23 | assertTrue(looksLikeError("Error in nested call from some location.\n"));
24 | assertTrue(looksLikeError("Error in nested call from some.location.with.periods.\n"));
25 | assertTrue(looksLikeError("Error in nested call from some location: some message\n"));
26 | assertTrue(looksLikeError("Error in nested call from some.location.with.periods: some message\n"));
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/test/schemely/completion/SchemeIdentifierMatcherTest.java:
--------------------------------------------------------------------------------
1 | package schemely.completion;
2 |
3 | import junit.framework.TestCase;
4 |
5 | /**
6 | * @author Colin Fleming
7 | */
8 | public class SchemeIdentifierMatcherTest extends TestCase
9 | {
10 | public void testBasicMatching()
11 | {
12 | match("str", "string");
13 | match("STR", "string");
14 | match("string", "string");
15 | match("str-app", "string-append");
16 | match("c-w-c-c", "call-with-current-continuation");
17 | match("*-append", "string-append");
18 | doesntMatch("strings", "string");
19 | doesntMatch("strings", "string-append");
20 | doesntMatch("crud-w-c-c", "call-with-current-continuation");
21 | }
22 |
23 | public void match(String prefix, String test)
24 | {
25 | match(prefix, test, false);
26 | }
27 |
28 | public void match(String prefix, String test, boolean caseSensitive)
29 | {
30 | assertTrue(new SchemeIdentifierMatcher(prefix, caseSensitive).prefixMatches(test));
31 | }
32 |
33 | public void doesntMatch(String prefix, String test)
34 | {
35 | doesntMatch(prefix, test, false);
36 | }
37 |
38 | public void doesntMatch(String prefix, String test, boolean caseSensitive)
39 | {
40 | assertFalse(new SchemeIdentifierMatcher(prefix, caseSensitive).prefixMatches(test));
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/schemely/psi/impl/symbols/SymbolUtils.java:
--------------------------------------------------------------------------------
1 | package schemely.psi.impl.symbols;
2 |
3 | import com.intellij.psi.PsiElement;
4 | import com.intellij.psi.util.PsiTreeUtil;
5 | import schemely.psi.impl.list.SchemeList;
6 |
7 | import javax.swing.*;
8 |
9 |
10 | public class SymbolUtils
11 | {
12 |
13 | public static Icon getIcon(SchemeIdentifier symbol, int flags)
14 | {
15 | PsiElement parent = PsiTreeUtil.getParentOfType(symbol, SchemeList.class);
16 | if (parent instanceof SchemeList)
17 | {
18 | SchemeList list = (SchemeList) parent;
19 |
20 | // Functions and defs
21 | if (symbol == list.getSecondNonLeafElement())
22 | {
23 | PsiElement fst = list.getFirstNonLeafElement();
24 | if (fst instanceof SchemeIdentifier)
25 | {
26 | SchemeIdentifier lstSym = (SchemeIdentifier) fst;
27 | String nameString = lstSym.getNameString();
28 |
29 | // if (FN.equals(nameString))
30 | // {
31 | // return SchemeIcons.FUNCTION;
32 | // }
33 | // if (DEFN.equals(nameString))
34 | // {
35 | // return SchemeIcons.FUNCTION;
36 | // }
37 | }
38 | }
39 |
40 |
41 | }
42 |
43 | return null;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/schemely/scheme/sisc/psi/SISCPsiCreator.java:
--------------------------------------------------------------------------------
1 | package schemely.scheme.sisc.psi;
2 |
3 | import com.intellij.lang.ASTNode;
4 | import com.intellij.psi.FileViewProvider;
5 | import com.intellij.psi.PsiElement;
6 | import com.intellij.psi.PsiFile;
7 | import com.intellij.psi.tree.IElementType;
8 | import schemely.parser.AST;
9 | import schemely.parser.SchemePsiCreator;
10 | import schemely.scheme.sisc.parser.SISCAST;
11 |
12 | /**
13 | * @author Colin Fleming
14 | */
15 | public class SISCPsiCreator implements SchemePsiCreator
16 | {
17 | private final SchemePsiCreator original;
18 |
19 | public SISCPsiCreator(SchemePsiCreator original)
20 | {
21 | this.original = original;
22 | }
23 |
24 | @Override
25 | public PsiElement createElement(ASTNode node)
26 | {
27 | IElementType elementType = node.getElementType();
28 |
29 | if (elementType == AST.LIST)
30 | {
31 | return new SISCList(node);
32 | }
33 | else if (elementType == SISCAST.PTR_DEF)
34 | {
35 | return new SISCPointerDef(node);
36 | }
37 | else if (elementType == SISCAST.PTR_REF)
38 | {
39 | return new SISCPointerRef(node);
40 | }
41 | return original.createElement(node);
42 | }
43 |
44 | @Override
45 | public PsiFile createFile(FileViewProvider viewProvider)
46 | {
47 | return new SISCFile(viewProvider);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/schemely/repl/toolwindow/actions/REPLEnterAction.java:
--------------------------------------------------------------------------------
1 | package schemely.repl.toolwindow.actions;
2 |
3 | import com.intellij.openapi.actionSystem.DataContext;
4 | import com.intellij.openapi.editor.Editor;
5 | import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
6 | import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
7 | import com.intellij.openapi.project.DumbAware;
8 | import schemely.scheme.REPL;
9 |
10 | /**
11 | * @author Colin Fleming
12 | */
13 | public class REPLEnterAction extends EditorWriteActionHandler implements DumbAware
14 | {
15 | private final EditorActionHandler originalHandler;
16 |
17 | public REPLEnterAction(EditorActionHandler originalHandler)
18 | {
19 | this.originalHandler = originalHandler;
20 | }
21 |
22 | @Override
23 | public void executeWriteAction(Editor editor, DataContext dataContext)
24 | {
25 | REPL repl = editor.getUserData(REPL.REPL_KEY);
26 | if (repl == null)
27 | {
28 | originalHandler.execute(editor, dataContext);
29 | }
30 | else if (!repl.getConsoleView().getConsole().executeCurrent(false))
31 | {
32 | originalHandler.execute(editor, dataContext);
33 | }
34 | }
35 |
36 | @Override
37 | public boolean isEnabled(Editor editor, DataContext dataContext)
38 | {
39 | return originalHandler.isEnabled(editor, dataContext);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/schemely/psi/stubs/impl/SchemeFileStubImpl.java:
--------------------------------------------------------------------------------
1 | package schemely.psi.stubs.impl;
2 |
3 | import com.intellij.psi.stubs.PsiFileStubImpl;
4 | import com.intellij.psi.tree.IStubFileElementType;
5 | import com.intellij.util.io.StringRef;
6 | import schemely.parser.AST;
7 | import schemely.psi.impl.SchemeFile;
8 | import schemely.psi.stubs.api.SchemeFileStub;
9 |
10 |
11 | public class SchemeFileStubImpl extends PsiFileStubImpl implements SchemeFileStub
12 | {
13 | private final StringRef packageName;
14 | private final StringRef name;
15 | private final boolean isClassDefinition;
16 |
17 | public SchemeFileStubImpl(SchemeFile file)
18 | {
19 | super(file);
20 | packageName = StringRef.fromString(file.getPackageName());
21 | isClassDefinition = false;
22 | name = StringRef.fromString(null);
23 | }
24 |
25 | public SchemeFileStubImpl(StringRef packName, StringRef name, boolean isScript)
26 | {
27 | super(null);
28 | packageName = packName;
29 | this.name = name;
30 | this.isClassDefinition = isScript;
31 | }
32 |
33 | public IStubFileElementType getType()
34 | {
35 | return AST.FILE;
36 | }
37 |
38 | public StringRef getPackageName()
39 | {
40 | return packageName;
41 | }
42 |
43 | public StringRef getName()
44 | {
45 | return name;
46 | }
47 |
48 | public boolean isClassDefinition()
49 | {
50 | return isClassDefinition;
51 | }
52 | }
--------------------------------------------------------------------------------
/src/schemely/utils/Actions.java:
--------------------------------------------------------------------------------
1 | package schemely.utils;
2 |
3 | import com.intellij.openapi.actionSystem.AnActionEvent;
4 | import com.intellij.openapi.actionSystem.DataKeys;
5 | import com.intellij.openapi.module.Module;
6 | import com.intellij.openapi.module.ModuleManager;
7 | import com.intellij.openapi.project.Project;
8 |
9 | /**
10 | * @author Colin Fleming
11 | */
12 | public class Actions
13 | {
14 | public static Module getModule(AnActionEvent e)
15 | {
16 | Module module = e.getData(DataKeys.MODULE);
17 | if (module == null)
18 | {
19 | Project project = e.getData(DataKeys.PROJECT);
20 |
21 | if (project == null)
22 | {
23 | return null;
24 | }
25 | Module[] modules = ModuleManager.getInstance(project).getModules();
26 | if (modules.length == 1)
27 | {
28 | module = modules[0];
29 | }
30 | else
31 | {
32 | // for (Module m : modules)
33 | // {
34 | // FacetManager manager = FacetManager.getInstance(m);
35 | // SchemeFacet clFacet = manager.getFacetByType(SchemeFacetType.INSTANCE.getId());
36 | // if (clFacet != null)
37 | // {
38 | // module = m;
39 | // break;
40 | // }
41 | // }
42 | if (module == null)
43 | {
44 | module = modules[0];
45 | }
46 | }
47 | }
48 | return module;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/schemely/repl/toolwindow/actions/ExecuteImmediatelyAction.java:
--------------------------------------------------------------------------------
1 | package schemely.repl.toolwindow.actions;
2 |
3 | import com.intellij.openapi.actionSystem.AnActionEvent;
4 | import com.intellij.openapi.actionSystem.EmptyAction;
5 | import com.intellij.openapi.project.DumbAwareAction;
6 | import com.intellij.openapi.util.IconLoader;
7 | import schemely.repl.SchemeConsole;
8 | import schemely.scheme.REPL;
9 |
10 | import javax.swing.*;
11 |
12 | /**
13 | * @author Colin Fleming
14 | */
15 | public class ExecuteImmediatelyAction extends DumbAwareAction
16 | {
17 | private static final Icon ACTIONS_EXECUTE_ICON = IconLoader.getIcon("/actions/execute.png");
18 | private static final String EXECUTE_IMMEDIATELY_ID = "Scheme.REPL.Execute.Immediately";
19 |
20 | private final SchemeConsole console;
21 |
22 | public ExecuteImmediatelyAction(SchemeConsole console)
23 | {
24 | super(null, null, ACTIONS_EXECUTE_ICON);
25 | this.console = console;
26 | EmptyAction.setupAction(this, EXECUTE_IMMEDIATELY_ID, null);
27 | }
28 |
29 | @Override
30 | public void update(AnActionEvent e)
31 | {
32 | REPL repl = console.getConsoleEditor().getUserData(REPL.REPL_KEY);
33 | if (repl != null)
34 | {
35 | e.getPresentation().setEnabled(repl.isActive());
36 | }
37 | }
38 |
39 | @Override
40 | public void actionPerformed(AnActionEvent e)
41 | {
42 | console.executeCurrent(true);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/schemely/formatter/SchemeFormattingModelBuilder.java:
--------------------------------------------------------------------------------
1 | package schemely.formatter;
2 |
3 | import com.intellij.formatting.FormattingModel;
4 | import com.intellij.formatting.FormattingModelBuilder;
5 | import com.intellij.formatting.FormattingModelProvider;
6 | import com.intellij.formatting.Indent;
7 | import com.intellij.lang.ASTNode;
8 | import com.intellij.openapi.util.TextRange;
9 | import com.intellij.psi.PsiElement;
10 | import com.intellij.psi.PsiFile;
11 | import com.intellij.psi.codeStyle.CodeStyleSettings;
12 | import org.jetbrains.annotations.NotNull;
13 | import org.jetbrains.annotations.Nullable;
14 |
15 |
16 | public class SchemeFormattingModelBuilder implements FormattingModelBuilder
17 | {
18 | @NotNull
19 | public FormattingModel createModel(PsiElement element, CodeStyleSettings settings)
20 | {
21 | ASTNode node = element.getNode();
22 | assert node != null;
23 | PsiFile containingFile = element.getContainingFile();
24 | ASTNode astNode = containingFile.getNode();
25 | assert astNode != null;
26 | SchemeBlock schemeBlock = SchemeBlock.create(astNode, null, Indent.getAbsoluteNoneIndent(), null, settings);
27 | return FormattingModelProvider.createFormattingModelForPsiFile(containingFile, schemeBlock, settings);
28 | }
29 |
30 | @Nullable
31 | public TextRange getRangeAffectingIndent(PsiFile file, int offset, ASTNode elementAtOffset)
32 | {
33 | return null;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/schemely/editor/selection/SchemeIdentifierSelectioner.java:
--------------------------------------------------------------------------------
1 | package schemely.editor.selection;
2 |
3 | import com.intellij.codeInsight.editorActions.ExtendWordSelectionHandler;
4 | import com.intellij.openapi.editor.Editor;
5 | import com.intellij.openapi.util.Condition;
6 | import com.intellij.openapi.util.TextRange;
7 | import com.intellij.psi.PsiElement;
8 | import schemely.psi.impl.symbols.SchemeIdentifier;
9 |
10 | import java.util.Collections;
11 | import java.util.List;
12 |
13 | /**
14 | * @author Colin Fleming
15 | */
16 | public class SchemeIdentifierSelectioner implements ExtendWordSelectionHandler
17 | {
18 | @Override
19 | public boolean canSelect(PsiElement e)
20 | {
21 | PsiElement parent = e.getParent();
22 | return (e instanceof SchemeIdentifier) || (parent instanceof SchemeIdentifier);
23 | }
24 |
25 | @Override
26 | public List select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor)
27 | {
28 | return Collections.singletonList(e.getTextRange());
29 | }
30 |
31 | // Don't allow normal word selection for identifiers
32 | public static class BasicWordRestriction implements Condition
33 | {
34 | @Override
35 | public boolean value(PsiElement element)
36 | {
37 | PsiElement parent = element.getParent();
38 | return !((element instanceof SchemeIdentifier) || (parent instanceof SchemeIdentifier));
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/schemely/repl/SchemeConsoleElement.java:
--------------------------------------------------------------------------------
1 | package schemely.repl;
2 |
3 | import com.intellij.psi.PsiElement;
4 | import com.intellij.psi.PsiManager;
5 | import com.intellij.psi.PsiNamedElement;
6 | import com.intellij.psi.impl.light.LightElement;
7 | import com.intellij.util.IncorrectOperationException;
8 | import org.jetbrains.annotations.NonNls;
9 | import org.jetbrains.annotations.NotNull;
10 | import schemely.file.SchemeFileType;
11 |
12 | /**
13 | * @author Colin Fleming
14 | */
15 | public class SchemeConsoleElement extends LightElement implements PsiNamedElement
16 | {
17 | @NotNull
18 | private final String name;
19 |
20 | public SchemeConsoleElement(PsiManager manager, @NotNull String name)
21 | {
22 | super(manager, SchemeFileType.SCHEME_LANGUAGE);
23 | this.name = name;
24 | }
25 |
26 | @Override
27 | public String getText()
28 | {
29 | return name;
30 | }
31 |
32 | @Override
33 | public PsiElement copy()
34 | {
35 | return null;
36 | }
37 |
38 | @Override
39 | @NotNull
40 | public String getName()
41 | {
42 | return name;
43 | }
44 |
45 | @Override
46 | public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException
47 | {
48 | throw new UnsupportedOperationException("Can't set name for console elements");
49 | }
50 |
51 | @Override
52 | public String toString()
53 | {
54 | return "Console element " + name;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/src/schemely/scheme/kawa/KawaScheme.java:
--------------------------------------------------------------------------------
1 | package schemely.scheme.kawa;
2 |
3 | import com.intellij.lang.PsiParser;
4 | import com.intellij.lexer.Lexer;
5 | import schemely.lexer.SchemeLexer;
6 | import schemely.parser.DefaultPsiCreator;
7 | import schemely.parser.SchemeParser;
8 | import schemely.parser.SchemePsiCreator;
9 | import schemely.repl.REPLProvider;
10 | import schemely.repl.UnsupportedREPLProvider;
11 | import schemely.scheme.Scheme;
12 |
13 | /**
14 | * @author Colin Fleming
15 | */
16 | public class KawaScheme implements Scheme
17 | {
18 | private static final UnsupportedREPLProvider IN_PROCESS_PROVIDER = new UnsupportedREPLProvider();
19 | private static final UnsupportedREPLProvider EXTERNAL_PROVIDER = new UnsupportedREPLProvider();
20 |
21 | @Override
22 | public Lexer getLexer()
23 | {
24 | return new SchemeLexer();
25 | }
26 |
27 | @Override
28 | public PsiParser getParser()
29 | {
30 | return new SchemeParser();
31 | }
32 |
33 | @Override
34 | public SchemePsiCreator getPsiCreator()
35 | {
36 | return new DefaultPsiCreator();
37 | }
38 |
39 | @Override
40 | public boolean supportsSquareBracesForLists()
41 | {
42 | return false;
43 | }
44 |
45 | @Override
46 | public REPLProvider getInProcessREPLProvider()
47 | {
48 | return IN_PROCESS_PROVIDER;
49 | }
50 |
51 | @Override
52 | public REPLProvider getExternalREPLProvider()
53 | {
54 | return EXTERNAL_PROVIDER;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/schemely/scheme/sisc/parser/SISCParser.java:
--------------------------------------------------------------------------------
1 | package schemely.scheme.sisc.parser;
2 |
3 | import com.intellij.lang.PsiBuilder;
4 | import com.intellij.psi.tree.IElementType;
5 | import com.intellij.psi.tree.TokenSet;
6 | import schemely.parser.SchemeParser;
7 | import schemely.scheme.sisc.lexer.SISCTokens;
8 |
9 | /**
10 | * @author Colin Fleming
11 | */
12 | public class SISCParser extends SchemeParser
13 | {
14 | private static final TokenSet SISC_PREFIXES = TokenSet.orSet(PREFIXES, TokenSet.create(SISCTokens.SYNTAX_QUOTE));
15 |
16 | @Override
17 | protected void parseDatum(PsiBuilder builder)
18 | {
19 | IElementType token = builder.getTokenType();
20 | if (SISCTokens.PTR_DEF == token)
21 | {
22 | parsePtrDef(builder);
23 | }
24 | else if (SISCTokens.PTR_REF == token)
25 | {
26 | parsePtrRef(builder);
27 | }
28 | else
29 | {
30 | super.parseDatum(builder);
31 | }
32 | }
33 |
34 | private void parsePtrDef(PsiBuilder builder)
35 | {
36 | PsiBuilder.Marker marker = builder.mark();
37 | builder.advanceLexer();
38 | parseDatum(builder);
39 | marker.done(SISCAST.PTR_DEF);
40 | }
41 |
42 | private void parsePtrRef(PsiBuilder builder)
43 | {
44 | PsiBuilder.Marker marker = builder.mark();
45 | builder.advanceLexer();
46 | marker.done(SISCAST.PTR_REF);
47 | }
48 |
49 | @Override
50 | protected TokenSet getPrefixes()
51 | {
52 | return SISC_PREFIXES;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/schemely/compiler/CompilerProjectComponent.java:
--------------------------------------------------------------------------------
1 | package schemely.compiler;
2 |
3 | import com.intellij.openapi.compiler.CompilerManager;
4 | import com.intellij.openapi.components.ProjectComponent;
5 | import com.intellij.openapi.project.Project;
6 | import org.jetbrains.annotations.NotNull;
7 | import schemely.file.SchemeFileType;
8 |
9 | /**
10 | * @author Colin Fleming
11 | */
12 | public class CompilerProjectComponent implements ProjectComponent
13 | {
14 | private final Project project;
15 |
16 | public CompilerProjectComponent(Project project)
17 | {
18 | this.project = project;
19 | }
20 |
21 | @Override
22 | public void projectOpened()
23 | {
24 | CompilerManager compilerManager = CompilerManager.getInstance(project);
25 | compilerManager.addCompilableFileType(SchemeFileType.SCHEME_FILE_TYPE);
26 |
27 | for (SchemeCompiler compiler : CompilerManager.getInstance(project).getCompilers(SchemeCompiler.class))
28 | {
29 | CompilerManager.getInstance(project).removeCompiler(compiler);
30 | }
31 | CompilerManager.getInstance(project).addCompiler(new SchemeCompiler(project));
32 | }
33 |
34 | @Override
35 | public void projectClosed()
36 | {
37 | }
38 |
39 | @NotNull
40 | @Override
41 | public String getComponentName()
42 | {
43 | return "CompilerProjectComponent";
44 | }
45 |
46 | @Override
47 | public void initComponent()
48 | {
49 | }
50 |
51 | @Override
52 | public void disposeComponent()
53 | {
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/schemely/scheme/sisc/SISCScheme.java:
--------------------------------------------------------------------------------
1 | package schemely.scheme.sisc;
2 |
3 | import com.intellij.lang.PsiParser;
4 | import com.intellij.lexer.Lexer;
5 | import schemely.parser.DefaultPsiCreator;
6 | import schemely.parser.SchemePsiCreator;
7 | import schemely.repl.REPLProvider;
8 | import schemely.scheme.Scheme;
9 | import schemely.scheme.sisc.lexer.SISCLexer;
10 | import schemely.scheme.sisc.parser.SISCParser;
11 | import schemely.scheme.sisc.psi.SISCPsiCreator;
12 |
13 | /**
14 | * @author Colin Fleming
15 | */
16 | public class SISCScheme implements Scheme
17 | {
18 | private static final SISCInProcessREPL.Provider IN_PROCESS_PROVIDER = new SISCInProcessREPL.Provider();
19 | private static final SISCProcessREPL.Provider EXTERNAL_PROVIDER = new SISCProcessREPL.Provider();
20 |
21 | @Override
22 | public Lexer getLexer()
23 | {
24 | return new SISCLexer();
25 | }
26 |
27 | @Override
28 | public PsiParser getParser()
29 | {
30 | return new SISCParser();
31 | }
32 |
33 | @Override
34 | public SchemePsiCreator getPsiCreator()
35 | {
36 | return new SISCPsiCreator(new DefaultPsiCreator());
37 | }
38 |
39 | @Override
40 | public boolean supportsSquareBracesForLists()
41 | {
42 | return true;
43 | }
44 |
45 | @Override
46 | public REPLProvider getInProcessREPLProvider()
47 | {
48 | return IN_PROCESS_PROVIDER;
49 | }
50 |
51 | @Override
52 | public REPLProvider getExternalREPLProvider()
53 | {
54 | return EXTERNAL_PROVIDER;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/schemely/structure/SchemeStructureViewModel.java:
--------------------------------------------------------------------------------
1 | package schemely.structure;
2 |
3 | import com.intellij.ide.structureView.StructureViewTreeElement;
4 | import com.intellij.ide.structureView.TextEditorBasedStructureViewModel;
5 | import com.intellij.ide.util.treeView.smartTree.Filter;
6 | import com.intellij.ide.util.treeView.smartTree.Grouper;
7 | import com.intellij.ide.util.treeView.smartTree.Sorter;
8 | import com.intellij.psi.PsiFile;
9 | import org.jetbrains.annotations.NotNull;
10 | import schemely.psi.impl.symbols.SchemeIdentifier;
11 |
12 |
13 | public class SchemeStructureViewModel extends TextEditorBasedStructureViewModel
14 | {
15 | private PsiFile file;
16 |
17 | public SchemeStructureViewModel(PsiFile file)
18 | {
19 | super(file);
20 | this.file = file;
21 | }
22 |
23 | @NotNull
24 | public StructureViewTreeElement getRoot()
25 | {
26 | return new SchemeStructureViewElement(file);
27 | }
28 |
29 | @NotNull
30 | public Grouper[] getGroupers()
31 | {
32 | return Grouper.EMPTY_ARRAY;
33 | }
34 |
35 | @NotNull
36 | public Sorter[] getSorters()
37 | {
38 | return new Sorter[] { Sorter.ALPHA_SORTER };
39 | }
40 |
41 | @NotNull
42 | public Filter[] getFilters()
43 | {
44 | return Filter.EMPTY_ARRAY;
45 | }
46 |
47 | protected PsiFile getPsiFile()
48 | {
49 | return file;
50 | }
51 |
52 | @NotNull
53 | protected Class[] getSuitableClasses()
54 | {
55 | return new Class[] { SchemeIdentifier.class };
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/schemely/editor/selection/SchemeListSelectioner.java:
--------------------------------------------------------------------------------
1 | package schemely.editor.selection;
2 |
3 | import com.intellij.codeInsight.editorActions.ExtendWordSelectionHandler;
4 | import com.intellij.openapi.editor.Editor;
5 | import com.intellij.openapi.util.TextRange;
6 | import com.intellij.psi.PsiElement;
7 | import schemely.psi.api.SchemeBraced;
8 | import schemely.psi.impl.SchemeVector;
9 | import schemely.psi.impl.list.SchemeList;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 |
14 |
15 | public class SchemeListSelectioner implements ExtendWordSelectionHandler
16 | {
17 | public boolean canSelect(PsiElement e)
18 | {
19 | return e instanceof SchemeList || e instanceof SchemeVector;
20 | }
21 |
22 | @Override
23 | public List select(PsiElement element, CharSequence editorText, int cursorOffset, Editor editor)
24 | {
25 | List result = new ArrayList();
26 | if (element instanceof SchemeBraced)
27 | {
28 | SchemeBraced list = (SchemeBraced) element;
29 | PsiElement left = list.getFirstBrace();
30 | PsiElement right = list.getLastBrace();
31 | if (right != null)
32 | {
33 | result.add(new TextRange(left.getTextRange().getStartOffset(), right.getTextRange().getEndOffset()));
34 | }
35 | else
36 | {
37 | result.add(new TextRange(left.getTextRange().getStartOffset(), element.getTextRange().getEndOffset()));
38 | }
39 | }
40 |
41 | return result;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/schemely/editor/SchemeQuoteHandler.java:
--------------------------------------------------------------------------------
1 | package schemely.editor;
2 |
3 | import com.intellij.codeInsight.editorActions.QuoteHandler;
4 | import com.intellij.openapi.editor.Editor;
5 | import com.intellij.openapi.editor.highlighter.HighlighterIterator;
6 | import com.intellij.psi.tree.IElementType;
7 | import schemely.lexer.Tokens;
8 |
9 |
10 | public class SchemeQuoteHandler implements QuoteHandler
11 | {
12 | public boolean isClosingQuote(HighlighterIterator iterator, int offset)
13 | {
14 | IElementType tokenType = iterator.getTokenType();
15 |
16 | if (tokenType == Tokens.STRING_LITERAL)
17 | {
18 | int start = iterator.getStart();
19 | int end = iterator.getEnd();
20 | return end - start >= 1 && offset == end - 1;
21 | }
22 | return false;
23 | }
24 |
25 | public boolean isOpeningQuote(HighlighterIterator iterator, int offset)
26 | {
27 | IElementType tokenType = iterator.getTokenType();
28 |
29 | // TODO CMF
30 | if (/*tokenType == Tokens.WRONG_STRING_LITERAL || */tokenType == Tokens.STRING_LITERAL)
31 | {
32 | int start = iterator.getStart();
33 | return offset == start;
34 | }
35 | return false;
36 | }
37 |
38 | public boolean hasNonClosedLiteral(Editor editor, HighlighterIterator iterator, int offset)
39 | {
40 | return true;
41 | }
42 |
43 | public boolean isInsideLiteral(HighlighterIterator iterator)
44 | {
45 | IElementType tokenType = iterator.getTokenType();
46 | return tokenType == Tokens.STRING_LITERAL;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/schemely/psi/impl/search/SchemeSourceFilterScope.java:
--------------------------------------------------------------------------------
1 | package schemely.psi.impl.search;
2 |
3 | import com.intellij.psi.search.GlobalSearchScope;
4 | import com.intellij.openapi.roots.ProjectFileIndex;
5 | import com.intellij.openapi.roots.ProjectRootManager;
6 | import com.intellij.openapi.project.Project;
7 | import com.intellij.openapi.vfs.VirtualFile;
8 | import com.intellij.openapi.module.Module;
9 | import org.jetbrains.annotations.NotNull;
10 |
11 |
12 | public class SchemeSourceFilterScope extends GlobalSearchScope
13 | {
14 | private final GlobalSearchScope delegate;
15 | private final ProjectFileIndex index;
16 |
17 | public SchemeSourceFilterScope(GlobalSearchScope delegate, Project project)
18 | {
19 | this.delegate = delegate;
20 | index = ProjectRootManager.getInstance(project).getFileIndex();
21 | }
22 |
23 | public boolean contains(VirtualFile file)
24 | {
25 | if (delegate != null && !delegate.contains(file))
26 | {
27 | return false;
28 | }
29 |
30 | return index.isInSourceContent(file) || index.isInLibraryClasses(file);
31 | }
32 |
33 | public int compare(VirtualFile file1, VirtualFile file2)
34 | {
35 | return delegate != null ? delegate.compare(file1, file2) : 0;
36 | }
37 |
38 | public boolean isSearchInModuleContent(@NotNull Module aModule)
39 | {
40 | return delegate == null || delegate.isSearchInModuleContent(aModule);
41 | }
42 |
43 | public boolean isSearchInLibraries()
44 | {
45 | return delegate == null || delegate.isSearchInLibraries();
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/schemely/highlighter/SchemeBraceMatcher.java:
--------------------------------------------------------------------------------
1 | package schemely.highlighter;
2 |
3 | import com.intellij.lang.BracePair;
4 | import com.intellij.lang.PairedBraceMatcher;
5 | import com.intellij.psi.PsiFile;
6 | import com.intellij.psi.tree.IElementType;
7 | import org.jetbrains.annotations.NotNull;
8 | import org.jetbrains.annotations.Nullable;
9 | import schemely.lexer.Tokens;
10 |
11 | public class SchemeBraceMatcher implements PairedBraceMatcher
12 | {
13 | private static final
14 | BracePair[]
15 | PAIRS =
16 | new BracePair[]{new BracePair(Tokens.LEFT_PAREN, Tokens.RIGHT_PAREN, true),
17 | new BracePair(Tokens.LEFT_SQUARE, Tokens.RIGHT_SQUARE, true),
18 | new BracePair(Tokens.LEFT_CURLY, Tokens.RIGHT_CURLY, true),
19 | new BracePair(Tokens.OPEN_VECTOR, Tokens.RIGHT_PAREN, true)};
20 |
21 | public BracePair[] getPairs()
22 | {
23 | return PAIRS;
24 | }
25 |
26 | public boolean isPairedBracesAllowedBeforeType(@NotNull IElementType lbraceType, @Nullable IElementType tokenType)
27 | {
28 | return tokenType == null ||
29 | Tokens.WHITESPACE_SET.contains(tokenType) ||
30 | Tokens.COMMENTS.contains(tokenType) ||
31 | tokenType == Tokens.COMMA ||
32 | tokenType == Tokens.RIGHT_SQUARE ||
33 | tokenType == Tokens.RIGHT_PAREN ||
34 | tokenType == Tokens.RIGHT_CURLY;
35 | }
36 |
37 | public int getCodeConstructStart(PsiFile file, int openingBraceOffset)
38 | {
39 | return openingBraceOffset;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/schemely/psi/resolve/processors/SymbolResolveProcessor.java:
--------------------------------------------------------------------------------
1 | package schemely.psi.resolve.processors;
2 |
3 | import com.intellij.openapi.util.Key;
4 | import com.intellij.psi.PsiElement;
5 | import com.intellij.psi.PsiNamedElement;
6 | import com.intellij.psi.ResolveState;
7 | import com.intellij.psi.scope.NameHint;
8 | import schemely.psi.resolve.SchemeResolveResult;
9 |
10 | import java.util.HashSet;
11 | import java.util.Set;
12 |
13 |
14 | public class SymbolResolveProcessor extends ResolveProcessor
15 | {
16 | private final Set processedElements = new HashSet();
17 |
18 | public SymbolResolveProcessor(String name)
19 | {
20 | super(name);
21 | }
22 |
23 | public boolean execute(PsiElement element, ResolveState resolveState)
24 | {
25 | if ((element instanceof PsiNamedElement) && !processedElements.contains(element))
26 | {
27 | PsiNamedElement namedElement = (PsiNamedElement) element;
28 |
29 | candidates.add(new SchemeResolveResult(namedElement));
30 | processedElements.add(namedElement);
31 |
32 | return false;
33 | }
34 |
35 | return true;
36 | }
37 |
38 | @Override
39 | public T getHint(Key hintKey)
40 | {
41 | if (hintKey.equals(NameHint.KEY))
42 | {
43 | return (T) this;
44 | }
45 | return null;
46 | }
47 |
48 | public String getName(ResolveState resolveState)
49 | {
50 | return name;
51 | }
52 |
53 | @Override
54 | public boolean shouldProcess(DeclaractionKind kind)
55 | {
56 | return true;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/schemely/utils/SchemeNamesValidator.java:
--------------------------------------------------------------------------------
1 | package schemely.utils;
2 |
3 | import com.intellij.lang.refactoring.NamesValidator;
4 | import com.intellij.openapi.project.Project;
5 | import com.intellij.psi.tree.IElementType;
6 | import schemely.lexer.Tokens;
7 | import schemely.parser.SchemeElementType;
8 |
9 | import java.util.Arrays;
10 | import java.util.HashSet;
11 | import java.util.Set;
12 |
13 | /**
14 | * @author Colin Fleming
15 | */
16 | public class SchemeNamesValidator implements NamesValidator
17 | {
18 | private static final Set specialIdentifiers = new HashSet();
19 |
20 | static
21 | {
22 | specialIdentifiers.addAll(Arrays.asList("+", "-", "..."));
23 | }
24 |
25 | public boolean isKeyword(String s, Project project)
26 | {
27 | // We have no keywords
28 | return false;
29 | }
30 |
31 | public boolean isIdentifier(String s, Project project)
32 | {
33 | if (specialIdentifiers.contains(s))
34 | {
35 | return true;
36 | }
37 |
38 | if (!isInitial(s.charAt(0)))
39 | {
40 | return false;
41 | }
42 |
43 | for (int i = 1; i < s.length(); i++)
44 | {
45 | if (!isSubsequent(s.charAt(i)))
46 | {
47 | return false;
48 | }
49 | }
50 |
51 | return true;
52 | }
53 |
54 | private boolean isInitial(char c)
55 | {
56 | return Character.isLetter(c) || ("!$%&*/:<=>?^_~".indexOf(c) >= 0);
57 | }
58 |
59 | private boolean isSubsequent(char c)
60 | {
61 | return isInitial(c) || Character.isDigit(c) || ("+-.@".indexOf(c) >= 0);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/schemely/settings/SchemeProjectSettings.java:
--------------------------------------------------------------------------------
1 | package schemely.settings;
2 |
3 | import com.intellij.openapi.components.PersistentStateComponent;
4 | import com.intellij.openapi.components.ServiceManager;
5 | import com.intellij.openapi.components.State;
6 | import com.intellij.openapi.components.Storage;
7 | import com.intellij.openapi.components.StorageScheme;
8 | import com.intellij.openapi.project.Project;
9 | import com.intellij.util.xmlb.XmlSerializerUtil;
10 | import schemely.scheme.SchemeImplementation;
11 |
12 |
13 | @State(
14 | name = SchemeConfigurable.PROJECT_SETTINGS,
15 | storages = {@Storage(id = "default", file = "$PROJECT_FILE$"), @Storage(id = "dir",
16 | file = "$PROJECT_CONFIG_DIR$/scheme_project.xml",
17 | scheme = StorageScheme.DIRECTORY_BASED)})
18 | public class SchemeProjectSettings implements PersistentStateComponent
19 | {
20 | public SchemeImplementation schemeImplementation = SchemeImplementation.SISC_1_16_6;
21 | public boolean arrowKeysNavigateHistory = false;
22 |
23 | @Override
24 | public SchemeProjectSettings getState()
25 | {
26 | return this;
27 | }
28 |
29 | @Override
30 | public void loadState(SchemeProjectSettings state)
31 | {
32 | XmlSerializerUtil.copyBean(state, this);
33 | }
34 |
35 | public static SchemeProjectSettings getInstance(Project project)
36 | {
37 | return ServiceManager.getService(project, SchemeProjectSettings.class);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/schemely/parser/DefaultPsiCreator.java:
--------------------------------------------------------------------------------
1 | package schemely.parser;
2 |
3 | import com.intellij.lang.ASTNode;
4 | import com.intellij.psi.FileViewProvider;
5 | import com.intellij.psi.PsiElement;
6 | import com.intellij.psi.PsiFile;
7 | import com.intellij.psi.tree.IElementType;
8 | import schemely.psi.impl.SchemeFile;
9 | import schemely.psi.impl.SchemeLiteral;
10 | import schemely.psi.impl.SchemeQuoted;
11 | import schemely.psi.impl.SchemeVector;
12 | import schemely.psi.impl.list.SchemeList;
13 | import schemely.psi.impl.symbols.SchemeIdentifier;
14 |
15 |
16 | public class DefaultPsiCreator implements SchemePsiCreator
17 | {
18 | public PsiElement createElement(ASTNode node)
19 | {
20 | IElementType elementType = node.getElementType();
21 |
22 | if (elementType == AST.LIST)
23 | {
24 | return new SchemeList(node);
25 | }
26 | if (elementType == AST.VECTOR)
27 | {
28 | return new SchemeVector(node);
29 | }
30 | if (elementType == AST.QUOTED)
31 | {
32 | return new SchemeQuoted(node);
33 | }
34 | if (elementType == AST.IDENTIFIER)
35 | {
36 | return new SchemeIdentifier(node);
37 | }
38 | if (elementType == AST.SPECIAL)
39 | {
40 | return new SchemeIdentifier(node);
41 | }
42 | if (elementType == AST.LITERAL)
43 | {
44 | return new SchemeLiteral(node);
45 | }
46 |
47 | throw new Error("Unexpected ASTNode: " + node.getElementType());
48 | }
49 |
50 | @Override
51 | public PsiFile createFile(FileViewProvider viewProvider)
52 | {
53 | return new SchemeFile(viewProvider);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/schemely/repl/actions/RunTopSExprAction.java:
--------------------------------------------------------------------------------
1 | package schemely.repl.actions;
2 |
3 | import com.intellij.openapi.actionSystem.AnActionEvent;
4 | import com.intellij.openapi.actionSystem.DataKeys;
5 | import com.intellij.openapi.editor.Editor;
6 | import com.intellij.openapi.project.Project;
7 | import com.intellij.openapi.ui.Messages;
8 | import com.intellij.psi.PsiElement;
9 | import schemely.SchemeBundle;
10 | import schemely.SchemeIcons;
11 | import schemely.psi.util.SchemePsiElementFactory;
12 | import schemely.psi.util.SchemePsiUtil;
13 |
14 | public final class RunTopSExprAction extends RunActionBase
15 | {
16 | public RunTopSExprAction()
17 | {
18 | getTemplatePresentation().setIcon(SchemeIcons.SCHEME_ICON);
19 | }
20 |
21 | public void actionPerformed(AnActionEvent event)
22 | {
23 | Editor editor = event.getData(DataKeys.EDITOR);
24 | if (editor == null)
25 | {
26 | return;
27 | }
28 |
29 | Project project = editor.getProject();
30 | if (project == null)
31 | {
32 | return;
33 | }
34 |
35 | PsiElement sexp = SchemePsiUtil.findTopSexpAroundCaret(editor);
36 | if (sexp == null)
37 | {
38 | return;
39 | }
40 |
41 | if (SchemePsiElementFactory.getInstance(project).hasSyntacticalErrors(sexp))
42 | {
43 | Messages.showErrorDialog(project,
44 | SchemeBundle.message("evaluate.incorrect.sexp"),
45 | SchemeBundle.message("evaluate.incorrect.cannot.evaluate"));
46 |
47 | return;
48 | }
49 |
50 | executeTextRange(editor, sexp.getTextRange());
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/schemely/formatter/processors/SchemeSpacingProcessor.java:
--------------------------------------------------------------------------------
1 | package schemely.formatter.processors;
2 |
3 | import com.intellij.formatting.Block;
4 | import com.intellij.formatting.Spacing;
5 | import com.intellij.lang.ASTNode;
6 | import com.intellij.psi.tree.IElementType;
7 | import schemely.formatter.SchemeBlock;
8 | import schemely.parser.AST;
9 |
10 |
11 | public class SchemeSpacingProcessor implements AST
12 | {
13 | private static final Spacing NO_SPACING = Spacing.createSpacing(0, 0, 0, false, 0);
14 | private static final Spacing NO_SPACING_WITH_NEWLINE = Spacing.createSpacing(0, 0, 0, true, 1);
15 | private static final Spacing COMMON_SPACING = Spacing.createSpacing(1, 1, 0, true, 100);
16 |
17 | public static Spacing getSpacing(Block child1, Block child2)
18 | {
19 | if (!(child1 instanceof SchemeBlock) || !(child2 instanceof SchemeBlock))
20 | {
21 | return null;
22 | }
23 | SchemeBlock block1 = (SchemeBlock) child1;
24 | SchemeBlock block2 = (SchemeBlock) child2;
25 |
26 | ASTNode node1 = block1.getNode();
27 | ASTNode node2 = block2.getNode();
28 |
29 | return getSpacingForAST(node1, node2);
30 | }
31 |
32 | public static Spacing getSpacingForAST(ASTNode node1, ASTNode node2)
33 | {
34 | IElementType type1 = node1.getElementType();
35 | IElementType type2 = node2.getElementType();
36 |
37 | if (PREFIXES.contains(type1))
38 | {
39 | return NO_SPACING;
40 | }
41 |
42 | if (BRACES.contains(type1) || BRACES.contains(type2))
43 | {
44 | return NO_SPACING_WITH_NEWLINE;
45 | }
46 |
47 | return COMMON_SPACING;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/test/schemely/lexer/LexerTestBase.java:
--------------------------------------------------------------------------------
1 | package schemely.lexer;
2 |
3 | import com.intellij.psi.tree.IElementType;
4 | import org.testng.annotations.Test;
5 |
6 | import java.util.Arrays;
7 |
8 | /**
9 | * @author Colin Fleming
10 | */
11 | public class LexerTestBase
12 | {
13 | protected static LexerTestCase testCase(String testData, IElementType... types)
14 | {
15 | return new LexerTestCase(testData, types);
16 | }
17 |
18 | @Test(dataProvider = "lexerTests", groups = "Schemely")
19 | public void testLexer(LexerTestCase testCase)
20 | {
21 | SchemeLexer lexer = getLexer();
22 | lexer.start(testCase.testData);
23 |
24 | for (int i = 0; i < testCase.types.length; i++)
25 | {
26 | IElementType expected = testCase.types[i];
27 |
28 | assert expected.equals(lexer.getTokenType()) : "Expected " + expected + ", got " + lexer.getTokenType();
29 | lexer.advance();
30 | }
31 |
32 | assert lexer.getTokenType() == null : "Expected final null, got " + lexer.getTokenType();
33 | }
34 |
35 | protected SchemeLexer getLexer()
36 | {
37 | return new SchemeLexer();
38 | }
39 |
40 | protected static class LexerTestCase
41 | {
42 | protected final String testData;
43 | protected final IElementType[] types;
44 |
45 | private LexerTestCase(String testData, IElementType... types)
46 | {
47 | this.testData = testData;
48 | this.types = types;
49 | }
50 |
51 | @Override
52 | public String toString()
53 | {
54 | return "LexerTestCase{" + testData + " -> " + (types == null ? null : Arrays.asList(types)) + '}';
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/schemely/repl/actions/RunLastSExprAction.java:
--------------------------------------------------------------------------------
1 | package schemely.repl.actions;
2 |
3 | import com.intellij.openapi.actionSystem.AnActionEvent;
4 | import com.intellij.openapi.actionSystem.PlatformDataKeys;
5 | import com.intellij.openapi.editor.Editor;
6 | import com.intellij.openapi.project.Project;
7 | import com.intellij.openapi.ui.Messages;
8 | import com.intellij.psi.PsiElement;
9 | import schemely.SchemeBundle;
10 | import schemely.SchemeIcons;
11 | import schemely.psi.util.SchemePsiElementFactory;
12 | import schemely.psi.util.SchemePsiUtil;
13 |
14 | public class RunLastSExprAction extends RunActionBase
15 | {
16 | public RunLastSExprAction()
17 | {
18 | getTemplatePresentation().setIcon(SchemeIcons.SCHEME_ICON);
19 | }
20 |
21 | @Override
22 | public void actionPerformed(AnActionEvent event)
23 | {
24 | Editor editor = event.getData(PlatformDataKeys.EDITOR);
25 | if (editor == null)
26 | {
27 | return;
28 | }
29 |
30 | Project project = editor.getProject();
31 | if (project == null)
32 | {
33 | return;
34 | }
35 |
36 | PsiElement sexp = SchemePsiUtil.findSexpAtCaret(editor, true);
37 | if (sexp == null)
38 | {
39 | return;
40 | }
41 |
42 | if (SchemePsiElementFactory.getInstance(project).hasSyntacticalErrors(sexp))
43 | {
44 | Messages.showErrorDialog(project,
45 | SchemeBundle.message("evaluate.incorrect.sexp"),
46 | SchemeBundle.message("evaluate.incorrect.cannot.evaluate"));
47 |
48 | return;
49 | }
50 |
51 | executeTextRange(editor, sexp.getTextRange());
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/schemely/highlighter/SchemeCommenter.java:
--------------------------------------------------------------------------------
1 | package schemely.highlighter;
2 |
3 | import com.intellij.lang.CodeDocumentationAwareCommenter;
4 | import com.intellij.psi.PsiComment;
5 | import com.intellij.psi.tree.IElementType;
6 | import org.jetbrains.annotations.Nullable;
7 | import schemely.lexer.Tokens;
8 |
9 |
10 | public class SchemeCommenter implements CodeDocumentationAwareCommenter, Tokens
11 | {
12 | public String getLineCommentPrefix()
13 | {
14 | return ";";
15 | }
16 |
17 | public String getBlockCommentPrefix()
18 | {
19 | return "#|";
20 | }
21 |
22 | public String getBlockCommentSuffix()
23 | {
24 | return "|#";
25 | }
26 |
27 | @Override
28 | public String getCommentedBlockCommentPrefix()
29 | {
30 | return "#|";
31 | }
32 |
33 | @Override
34 | public String getCommentedBlockCommentSuffix()
35 | {
36 | return "|#";
37 | }
38 |
39 | @Nullable
40 | public IElementType getLineCommentTokenType()
41 | {
42 | return COMMENT;
43 | }
44 |
45 | @Nullable
46 | public IElementType getBlockCommentTokenType()
47 | {
48 | return BLOCK_COMMENT;
49 | }
50 |
51 | @Nullable
52 | public IElementType getDocumentationCommentTokenType()
53 | {
54 | return null;
55 | }
56 |
57 | @Nullable
58 | public String getDocumentationCommentPrefix()
59 | {
60 | return null;
61 | }
62 |
63 | @Nullable
64 | public String getDocumentationCommentLinePrefix()
65 | {
66 | return null;
67 | }
68 |
69 | @Nullable
70 | public String getDocumentationCommentSuffix()
71 | {
72 | return null;
73 | }
74 |
75 | public boolean isDocumentationComment(PsiComment element)
76 | {
77 | return false;
78 | }
79 |
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/readme.markdown:
--------------------------------------------------------------------------------
1 | Schemely
2 | ========
3 |
4 | A Scheme support mode for IntelliJ 10
5 | -------------------------------------
6 |
7 | Schemely is an editing mode for Scheme code in IntelliJ 10. *This code is currently
8 | unstable and only suitable for enthusiastic alpha/beta testers*.
9 |
10 | ### Features:
11 |
12 | - Basics (paren matching, indenting, syntax highlighting)
13 | - Symbol navigation/Rename/Find Usages
14 | - Supports SISC and Kawa
15 | - Interactive REPL with history, completion and syntax highlighting
16 | - Compilation
17 | - Structure view
18 |
19 | Currently the code is undergoing some large changes, and lots of things don't work:
20 |
21 | - Kawa support is almost totally broken *(in fact it's currently disabled)*
22 | - Symbol resolution doesn't work across files
23 | - Symbol resolution (which affects navigation, rename and find usages) is currently broken
24 | in the face of macros
25 | - Structure view is almost totally broken
26 |
27 | Fixing at least the first 2 of these is my top priority and hopefully won't take too long.
28 |
29 | There is also a long list of planned features:
30 |
31 | - Finish running/compilation support
32 | - Proper support for modules
33 | - Customisable indentation
34 | - Cross-file symbol resolution (support import, load and friends)
35 | - Symbol resolution in the presence of macros (this is kind of hard)
36 | - Macro support (expand macro)
37 | - Extract function, extract variable, extract let binding
38 | - Paredit type support
39 | - Resolution of Java symbols for JVM-based Schemes
40 | - Racket support
41 | - Support for quirks of various implementations (case sensitivity etc)
42 | - Debugging support
43 | - Support for Android development with Kawa
44 | - Documentation
45 |
--------------------------------------------------------------------------------
/src/schemely/psi/impl/SchemeVector.java:
--------------------------------------------------------------------------------
1 | package schemely.psi.impl;
2 |
3 | import com.intellij.lang.ASTNode;
4 | import com.intellij.psi.PsiElement;
5 | import org.jetbrains.annotations.NotNull;
6 | import schemely.lexer.Tokens;
7 | import schemely.psi.api.SchemeBraced;
8 | import schemely.psi.api.SchemePsiElement;
9 | import schemely.psi.impl.list.SchemeList;
10 | import schemely.psi.impl.symbols.SchemeIdentifier;
11 |
12 | import java.util.ArrayList;
13 |
14 |
15 | public class SchemeVector extends SchemePsiElementBase implements SchemeBraced
16 | {
17 | public SchemeVector(ASTNode node)
18 | {
19 | super(node, "SchemeVector");
20 | }
21 |
22 | @NotNull
23 | public PsiElement getFirstBrace()
24 | {
25 | PsiElement element = findChildByType(Tokens.LEFT_SQUARE);
26 | assert element != null;
27 | return element;
28 | }
29 |
30 | public PsiElement getLastBrace()
31 | {
32 | return findChildByType(Tokens.RIGHT_SQUARE);
33 | }
34 |
35 | public SchemeIdentifier[] getAllSymbols()
36 | {
37 | return findChildrenByClass(SchemeIdentifier.class);
38 | }
39 |
40 | public SchemeList[] getSubLists()
41 | {
42 | return findChildrenByClass(SchemeList.class);
43 | }
44 |
45 | public SchemeIdentifier[] getOddSymbols()
46 | {
47 | SchemePsiElementBase[] elems = findChildrenByClass(SchemePsiElementBase.class);
48 | ArrayList res = new ArrayList();
49 | for (int i = 0; i < elems.length; i++)
50 | {
51 | SchemePsiElement elem = elems[i];
52 | if (i % 2 == 0 && elem instanceof SchemeIdentifier)
53 | {
54 | res.add((SchemeIdentifier) elem);
55 | }
56 | }
57 | return res.toArray(new SchemeIdentifier[res.size()]);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/schemely/repl/actions/RunSelectedTextAction.java:
--------------------------------------------------------------------------------
1 | package schemely.repl.actions;
2 |
3 | import com.intellij.openapi.actionSystem.AnActionEvent;
4 | import com.intellij.openapi.actionSystem.DataKeys;
5 | import com.intellij.openapi.editor.Editor;
6 | import com.intellij.openapi.editor.SelectionModel;
7 | import com.intellij.openapi.project.Project;
8 | import com.intellij.openapi.ui.Messages;
9 | import com.intellij.openapi.util.TextRange;
10 | import schemely.SchemeBundle;
11 | import schemely.SchemeIcons;
12 | import schemely.psi.util.SchemePsiElementFactory;
13 |
14 | public class RunSelectedTextAction extends RunActionBase
15 | {
16 | public RunSelectedTextAction()
17 | {
18 | getTemplatePresentation().setIcon(SchemeIcons.SCHEME_ICON);
19 | }
20 |
21 | public void actionPerformed(AnActionEvent e)
22 | {
23 | Editor editor = e.getData(DataKeys.EDITOR);
24 | if (editor == null)
25 | {
26 | return;
27 | }
28 | SelectionModel selectionModel = editor.getSelectionModel();
29 | String selectedText = selectionModel.getSelectedText();
30 | if ((selectedText == null) || (selectedText.trim().length() == 0))
31 | {
32 | return;
33 | }
34 | String text = selectedText.trim();
35 | Project project = editor.getProject();
36 |
37 | if (SchemePsiElementFactory.getInstance(project).hasSyntacticalErrors(text))
38 | {
39 | Messages.showErrorDialog(project,
40 | SchemeBundle.message("evaluate.incorrect.form"),
41 | SchemeBundle.message("evaluate.incorrect.cannot.evaluate", new Object[0]));
42 |
43 | return;
44 | }
45 |
46 | executeTextRange(editor, new TextRange(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()));
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/schemely/compiler/SchemeCompilerSettings.java:
--------------------------------------------------------------------------------
1 | package schemely.compiler;
2 |
3 | import com.intellij.openapi.components.*;
4 | import com.intellij.openapi.project.Project;
5 | import com.intellij.util.xmlb.XmlSerializerUtil;
6 | import org.jetbrains.annotations.NotNull;
7 |
8 | /**
9 | * @author Colin Fleming
10 | */
11 | @State(
12 | name = "SchemeCompilerSettings",
13 | storages = {
14 | @Storage(id = "default", file = "$PROJECT_FILE$")
15 | ,@Storage(id = "dir", file = "$PROJECT_CONFIG_DIR$/scheme_compiler.xml", scheme = StorageScheme.DIRECTORY_BASED)
16 | }
17 | )
18 | public class SchemeCompilerSettings implements PersistentStateComponent, ProjectComponent
19 | {
20 | public String prefix = "";
21 | public boolean modulesDefaultToStatic = true;
22 | public boolean warnUnknownMember = true;
23 | public boolean warnInvokeUnknownMethod = true;
24 | public boolean warnUndefinedVariable = true;
25 | public boolean warningsAsErrors = false;
26 |
27 | @NotNull
28 | @Override
29 | public String getComponentName()
30 | {
31 | return "SchemeCompilerSettings";
32 | }
33 |
34 | @Override
35 | public void initComponent()
36 | {
37 | }
38 |
39 | @Override
40 | public void disposeComponent()
41 | {
42 | }
43 |
44 | @Override
45 | public SchemeCompilerSettings getState()
46 | {
47 | return this;
48 | }
49 |
50 | @Override
51 | public void loadState(SchemeCompilerSettings state)
52 | {
53 | XmlSerializerUtil.copyBean(state, this);
54 | }
55 |
56 | @Override
57 | public void projectOpened()
58 | {
59 | }
60 |
61 | @Override
62 | public void projectClosed()
63 | {
64 | }
65 |
66 | public static SchemeCompilerSettings getInstance(Project project) {
67 | return project.getComponent(SchemeCompilerSettings.class);
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/schemely/repl/toolwindow/actions/NewExternalConsoleAction.java:
--------------------------------------------------------------------------------
1 | package schemely.repl.toolwindow.actions;
2 |
3 | import com.intellij.openapi.actionSystem.AnAction;
4 | import com.intellij.openapi.actionSystem.AnActionEvent;
5 | import com.intellij.openapi.actionSystem.Presentation;
6 | import com.intellij.openapi.module.Module;
7 | import com.intellij.openapi.project.DumbAware;
8 | import com.intellij.openapi.project.Project;
9 | import schemely.SchemeIcons;
10 | import schemely.repl.REPLProvider;
11 | import schemely.scheme.Scheme;
12 | import schemely.scheme.SchemeImplementation;
13 | import schemely.utils.Actions;
14 |
15 | public class NewExternalConsoleAction extends AnAction implements DumbAware
16 | {
17 | public NewExternalConsoleAction()
18 | {
19 | getTemplatePresentation().setIcon(SchemeIcons.SCHEME_ICON);
20 | }
21 |
22 | public void update(AnActionEvent e)
23 | {
24 | Module m = Actions.getModule(e);
25 | Presentation presentation = e.getPresentation();
26 | if (m == null)
27 | {
28 | presentation.setEnabled(false);
29 | return;
30 | }
31 |
32 | Scheme scheme = SchemeImplementation.from(m.getProject());
33 | REPLProvider provider = scheme.getExternalREPLProvider();
34 | presentation.setEnabled(provider.isSupported());
35 | super.update(e);
36 | }
37 |
38 | public void actionPerformed(AnActionEvent event)
39 | {
40 | Module module = Actions.getModule(event);
41 | assert (module != null) : "Module is null";
42 |
43 | // Find the tool window
44 | Project project = module.getProject();
45 | Scheme scheme = SchemeImplementation.from(project);
46 | REPLProvider provider = scheme.getExternalREPLProvider();
47 | if (!provider.isSupported())
48 | {
49 | return;
50 | }
51 |
52 | provider.createREPL(project, module);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/schemely/repl/toolwindow/actions/NewInProcessConsoleAction.java:
--------------------------------------------------------------------------------
1 | package schemely.repl.toolwindow.actions;
2 |
3 | import com.intellij.openapi.actionSystem.AnAction;
4 | import com.intellij.openapi.actionSystem.AnActionEvent;
5 | import com.intellij.openapi.actionSystem.Presentation;
6 | import com.intellij.openapi.module.Module;
7 | import com.intellij.openapi.project.DumbAware;
8 | import com.intellij.openapi.project.Project;
9 | import schemely.SchemeIcons;
10 | import schemely.repl.REPLProvider;
11 | import schemely.scheme.Scheme;
12 | import schemely.scheme.SchemeImplementation;
13 | import schemely.utils.Actions;
14 |
15 | public class NewInProcessConsoleAction extends AnAction implements DumbAware
16 | {
17 | public NewInProcessConsoleAction()
18 | {
19 | getTemplatePresentation().setIcon(SchemeIcons.SCHEME_ICON);
20 | }
21 |
22 | public void update(AnActionEvent e)
23 | {
24 | Module m = Actions.getModule(e);
25 | Presentation presentation = e.getPresentation();
26 | if (m == null)
27 | {
28 | presentation.setEnabled(false);
29 | return;
30 | }
31 |
32 | Scheme scheme = SchemeImplementation.from(m.getProject());
33 | REPLProvider provider = scheme.getInProcessREPLProvider();
34 | presentation.setEnabled(provider.isSupported());
35 | super.update(e);
36 | }
37 |
38 | public void actionPerformed(AnActionEvent event)
39 | {
40 | Module module = Actions.getModule(event);
41 | assert (module != null) : "Module is null";
42 |
43 | // Find the tool window
44 | Project project = module.getProject();
45 | Scheme scheme = SchemeImplementation.from(project);
46 | REPLProvider provider = scheme.getInProcessREPLProvider();
47 | if (!provider.isSupported())
48 | {
49 | return;
50 | }
51 |
52 | provider.createREPL(project, module);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/scheme-src/test.scm:
--------------------------------------------------------------------------------
1 | ;; Test highlighting
2 |
3 | (define string "Some string")
4 |
5 | (define quoted '(my quoted 3 items "with quoted string"))
6 |
7 | (define char #\c)
8 |
9 | (define special #!eof)
10 |
11 | (tmp)
12 |
13 | (let ((x '(1 3 5 7 9)))
14 | (do ((x x (cdr x))
15 | (sum 0 (+ sum (car x))))
16 | ((null? x) sum)))
17 |
18 | (do ((vec (make-vector 5))
19 | (i 0 (+ i 1)))
20 | ((= i 5) vec)
21 | (vector-set! vec i i))
22 |
23 | (let loop ((numbers '(3 -2 1 6 -5))
24 | (nonneg '())
25 | (neg '()))
26 | (cond ((null? numbers) (list nonneg neg))
27 | ((>= (car numbers) 0)
28 | (loop (cdr numbers)
29 | (cons (car numbers) nonneg)
30 | neg))
31 | ((< (car numbers) 0)
32 | (loop (cdr numbers)
33 | nonneg
34 | (cons (car numbers) neg)))))
35 |
36 | (let-syntax ((when (syntax-rules ()
37 | ((when test stmt1 stmt2 ...)
38 | (if test
39 | (begin stmt1
40 | stmt2 ...))))))
41 | (let ((if #t))
42 | (when if (set! if 'now))
43 | if))
44 |
45 | (let ((x 'outer))
46 | (let-syntax ((m (syntax-rules () ((m) x))))
47 | (let ((x 'inner))
48 | (m))))
49 |
50 | (define my-function
51 | (lambda (x)
52 | (+ x 2)))
53 |
54 | (letrec-syntax
55 | ((my-or (syntax-rules ()
56 | ((my-or) #f)
57 | ((my-or e) e)
58 | ((my-or e1 e2 ...)
59 | (let ((temp e1))
60 | (if temp
61 | temp
62 | (my-or e2 ...)))))))
63 | (let ((x #f)
64 | (y 7)
65 | (temp 8)
66 | (let odd?)
67 | (if even?))
68 | (my-or x
69 | (let temp)
70 | (if y)
71 | y)))
72 |
73 |
--------------------------------------------------------------------------------
/src/schemely/repl/actions/LoadSchemeFileInConsoleAction.java:
--------------------------------------------------------------------------------
1 | package schemely.repl.actions;
2 |
3 | import com.intellij.openapi.actionSystem.AnActionEvent;
4 | import com.intellij.openapi.actionSystem.DataKeys;
5 | import com.intellij.openapi.editor.Document;
6 | import com.intellij.openapi.editor.Editor;
7 | import com.intellij.openapi.fileEditor.FileDocumentManager;
8 | import com.intellij.openapi.project.Project;
9 | import com.intellij.openapi.vfs.VirtualFile;
10 | import com.intellij.psi.PsiDocumentManager;
11 | import com.intellij.psi.PsiFile;
12 | import schemely.SchemeIcons;
13 | import schemely.psi.impl.SchemeFile;
14 |
15 | public class LoadSchemeFileInConsoleAction extends RunActionBase
16 | {
17 | public LoadSchemeFileInConsoleAction()
18 | {
19 | getTemplatePresentation().setIcon(SchemeIcons.SCHEME_ICON);
20 | }
21 |
22 | public void actionPerformed(AnActionEvent e)
23 | {
24 | Editor editor = e.getData(DataKeys.EDITOR);
25 |
26 | if (editor == null)
27 | {
28 | return;
29 | }
30 | Project project = editor.getProject();
31 | if (project == null)
32 | {
33 | return;
34 | }
35 |
36 | Document document = editor.getDocument();
37 | PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document);
38 | if ((psiFile == null) || (!(psiFile instanceof SchemeFile)))
39 | {
40 | return;
41 | }
42 |
43 | VirtualFile virtualFile = psiFile.getVirtualFile();
44 | if (virtualFile == null)
45 | {
46 | return;
47 | }
48 | String filePath = virtualFile.getPath();
49 | if (filePath == null)
50 | {
51 | return;
52 | }
53 |
54 | String command = "(load \"" + filePath + "\")";
55 |
56 | PsiDocumentManager.getInstance(project).commitAllDocuments();
57 | FileDocumentManager.getInstance().saveAllDocuments();
58 |
59 | executeCommand(project, command);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/schemely/formatter/ListBlock.java:
--------------------------------------------------------------------------------
1 | package schemely.formatter;
2 |
3 | import com.intellij.formatting.Alignment;
4 | import com.intellij.formatting.Block;
5 | import com.intellij.formatting.ChildAttributes;
6 | import com.intellij.formatting.Indent;
7 | import com.intellij.formatting.Wrap;
8 | import com.intellij.lang.ASTNode;
9 | import com.intellij.psi.codeStyle.CodeStyleSettings;
10 | import org.jetbrains.annotations.NotNull;
11 | import org.jetbrains.annotations.Nullable;
12 | import schemely.lexer.Tokens;
13 |
14 | import java.util.ArrayList;
15 | import java.util.List;
16 |
17 | /**
18 | * @author Colin Fleming
19 | */
20 | public class ListBlock extends SchemeBlock
21 | {
22 | private final Alignment childAlignment = Alignment.createAlignment();
23 |
24 | public ListBlock(@NotNull ASTNode node,
25 | @Nullable Alignment alignment,
26 | @NotNull Indent indent,
27 | @Nullable Wrap wrap,
28 | CodeStyleSettings settings)
29 | {
30 | super(node, alignment, indent, wrap, settings);
31 | }
32 |
33 | @Override
34 | protected List generateSubBlocks(ASTNode node, Wrap wrap, CodeStyleSettings settings)
35 | {
36 | List subBlocks = new ArrayList();
37 | for (ASTNode childNode : getChildren(node))
38 | {
39 | Indent indent;
40 | Alignment align;
41 | if (Tokens.BRACES.contains(childNode.getElementType()))
42 | {
43 | indent = Indent.getNoneIndent();
44 | align = null;
45 | }
46 | else
47 | {
48 | indent = Indent.getNormalIndent(true);
49 | align = childAlignment;
50 | }
51 | subBlocks.add(SchemeBlock.create(childNode, align, indent, wrap, settings));
52 | }
53 | return subBlocks;
54 | }
55 |
56 | @Override
57 | protected ChildAttributes createChildAttributes(int newChildIndex)
58 | {
59 | return new ChildAttributes(Indent.getNormalIndent(true), childAlignment);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/schemely/formatter/SchemeIndentOptionsProvider.java:
--------------------------------------------------------------------------------
1 | package schemely.formatter;
2 |
3 | import com.intellij.application.options.IndentOptionsEditor;
4 | import com.intellij.application.options.SmartIndentOptionsEditor;
5 | import com.intellij.openapi.fileTypes.FileType;
6 | import com.intellij.psi.PsiFile;
7 | import com.intellij.psi.codeStyle.CodeStyleSettings;
8 | import com.intellij.psi.codeStyle.FileTypeIndentOptionsProvider;
9 | import schemely.file.SchemeFileType;
10 |
11 |
12 | public class SchemeIndentOptionsProvider implements FileTypeIndentOptionsProvider
13 | {
14 | public CodeStyleSettings.IndentOptions createIndentOptions()
15 | {
16 | CodeStyleSettings.IndentOptions indentOptions = new CodeStyleSettings.IndentOptions();
17 | indentOptions.INDENT_SIZE = 2;
18 | indentOptions.TAB_SIZE = 2;
19 | return indentOptions;
20 | }
21 |
22 | public FileType getFileType()
23 | {
24 | return SchemeFileType.SCHEME_FILE_TYPE;
25 | }
26 |
27 | public IndentOptionsEditor createOptionsEditor()
28 | {
29 | return new SmartIndentOptionsEditor();
30 | }
31 |
32 | public String getPreviewText()
33 | {
34 | return "(defn relay [x i]\n" +
35 | " (when (:next x)\n" +
36 | " (send (:next x) relay i))\n" +
37 | " (when (and (zero? i) (:report-queue x))\n" +
38 | " (.put (:report-queue x) i))\n" +
39 | " x)\n" +
40 | "\n" +
41 | "(defn run [m n]\n" +
42 | " (let [q (new java.util.concurrent.SynchronousQueue)\n" +
43 | " hd (reduce (fn [next _] (agent {:next next}))\n" +
44 | " (agent {:report-queue q}) (range (dec m)))]\n" +
45 | " (doseq [i (reverse (range n))]\n" +
46 | " (send hd relay i))\n" +
47 | " (.take q)))\n" +
48 | "\n" +
49 | "; 1 million message sends:\n" +
50 | "(time (run 1000 1000))";
51 | }
52 |
53 | public void prepareForReformat(PsiFile psiFile)
54 | {
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/schemely/utils/LibrariesUtil.java:
--------------------------------------------------------------------------------
1 | package schemely.utils;
2 |
3 | import com.intellij.openapi.application.ApplicationManager;
4 | import com.intellij.openapi.module.Module;
5 | import com.intellij.openapi.roots.*;
6 | import com.intellij.openapi.roots.libraries.Library;
7 | import com.intellij.openapi.roots.libraries.LibraryTable;
8 | import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar;
9 | import com.intellij.openapi.util.Condition;
10 | import com.intellij.util.containers.ContainerUtil;
11 |
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 |
16 | public class LibrariesUtil
17 | {
18 | public static Library[] getLibrariesByCondition(final Module module, final Condition condition)
19 | {
20 | if (module == null)
21 | {
22 | return new Library[0];
23 | }
24 | final ArrayList libraries = new ArrayList();
25 | ApplicationManager.getApplication().runReadAction(new Runnable()
26 | {
27 | public void run()
28 | {
29 | ModuleRootManager manager = ModuleRootManager.getInstance(module);
30 | ModifiableRootModel model = manager.getModifiableModel();
31 | for (OrderEntry entry : model.getOrderEntries())
32 | {
33 | if (entry instanceof LibraryOrderEntry)
34 | {
35 | LibraryOrderEntry libEntry = (LibraryOrderEntry) entry;
36 | Library library = libEntry.getLibrary();
37 | if (condition.value(library))
38 | {
39 | libraries.add(library);
40 | }
41 | }
42 | }
43 | model.dispose();
44 | }
45 | });
46 | return libraries.toArray(new Library[libraries.size()]);
47 | }
48 |
49 | public static Library[] getGlobalLibraries(Condition condition)
50 | {
51 | LibraryTable table = LibraryTablesRegistrar.getInstance().getLibraryTable();
52 | List libs = ContainerUtil.findAll(table.getLibraries(), condition);
53 | return libs.toArray(new Library[libs.size()]);
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/schemely/repl/LanguageConsoleViewImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2000-2010 JetBrains s.r.o.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package schemely.repl;
17 |
18 | import com.intellij.execution.impl.ConsoleViewImpl;
19 | import com.intellij.lang.Language;
20 | import com.intellij.openapi.editor.ex.EditorEx;
21 | import com.intellij.openapi.project.Project;
22 | import com.intellij.openapi.util.Disposer;
23 |
24 | import javax.swing.*;
25 |
26 | /**
27 | * @author Gregory.Shrago
28 | */
29 | public class LanguageConsoleViewImpl extends ConsoleViewImpl {
30 | protected LanguageConsoleImpl myConsole;
31 |
32 | protected LanguageConsoleViewImpl(Project project, LanguageConsoleImpl console) {
33 | super(project, true);
34 | myConsole = console;
35 | Disposer.register(this, myConsole);
36 | Disposer.register(project, this);
37 | }
38 |
39 | public LanguageConsoleImpl getConsole() {
40 | return myConsole;
41 | }
42 |
43 | @Override
44 | protected EditorEx createRealEditor() {
45 | return myConsole.getHistoryViewer();
46 | }
47 |
48 | @Override
49 | protected void disposeEditor() {
50 | }
51 |
52 | @Override
53 | protected JComponent createCenterComponent() {
54 | return myConsole.getComponent();
55 | }
56 |
57 | public JComponent getComponent() {
58 | return super.getComponent();
59 | }
60 |
61 | public JComponent getPreferredFocusableComponent() {
62 | return myConsole.getConsoleEditor().getContentComponent();
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/schemely/completion/SchemeCompletionContributor.java:
--------------------------------------------------------------------------------
1 | package schemely.completion;
2 |
3 | import com.intellij.codeInsight.completion.CompletionContributor;
4 | import com.intellij.codeInsight.completion.CompletionParameters;
5 | import com.intellij.codeInsight.completion.CompletionProvider;
6 | import com.intellij.codeInsight.completion.CompletionResultSet;
7 | import com.intellij.codeInsight.completion.CompletionType;
8 | import com.intellij.codeInsight.lookup.LookupElement;
9 | import com.intellij.patterns.ElementPattern;
10 | import com.intellij.psi.PsiElement;
11 | import com.intellij.util.ProcessingContext;
12 | import org.jetbrains.annotations.NotNull;
13 | import schemely.lexer.Tokens;
14 | import schemely.psi.impl.symbols.CompleteSymbol;
15 | import schemely.psi.impl.symbols.SchemeIdentifier;
16 |
17 | import static com.intellij.patterns.PlatformPatterns.or;
18 | import static com.intellij.patterns.PlatformPatterns.psiElement;
19 |
20 |
21 | public class SchemeCompletionContributor extends CompletionContributor
22 | {
23 | private static final ElementPattern IDENTIFIER =
24 | or(psiElement(SchemeIdentifier.class), psiElement(Tokens.IDENTIFIER));
25 |
26 | public SchemeCompletionContributor()
27 | {
28 | extend(CompletionType.BASIC, IDENTIFIER, new CompletionProvider()
29 | {
30 | @Override
31 | protected void addCompletions(@NotNull CompletionParameters parameters,
32 | ProcessingContext context,
33 | @NotNull CompletionResultSet result)
34 | {
35 | String prefix = parameters.getOriginalPosition().getText();
36 | result = result.withPrefixMatcher(new SchemeIdentifierMatcher(prefix));
37 | PsiElement position = parameters.getPosition();
38 | for (Object item : CompleteSymbol.getVariants(position))
39 | {
40 | if (item instanceof LookupElement)
41 | {
42 | result.addElement((LookupElement) item);
43 | }
44 | }
45 | }
46 | });
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/schemely/psi/util/SchemePsiElementFactoryImpl.java:
--------------------------------------------------------------------------------
1 | package schemely.psi.util;
2 |
3 | import com.intellij.lang.ASTNode;
4 | import com.intellij.openapi.project.Project;
5 | import com.intellij.psi.PsiElement;
6 | import com.intellij.psi.PsiErrorElement;
7 | import com.intellij.psi.PsiFileFactory;
8 | import org.jetbrains.annotations.NotNull;
9 | import schemely.file.SchemeFileType;
10 | import schemely.psi.impl.SchemeFile;
11 |
12 |
13 | public class SchemePsiElementFactoryImpl extends SchemePsiElementFactory
14 | {
15 | private final Project project;
16 |
17 | public SchemePsiElementFactoryImpl(Project project)
18 | {
19 | this.project = project;
20 | }
21 |
22 | private static final String DUMMY = "DUMMY.";
23 |
24 |
25 | public ASTNode createSymbolNodeFromText(@NotNull String newName)
26 | {
27 | String text = "(" + newName + ")";
28 | SchemeFile dummyFile = createSchemeFileFromText(text);
29 | return dummyFile.getFirstChild().getFirstChild().getNextSibling().getNode();
30 | }
31 |
32 | @Override
33 | public SchemeFile createSchemeFileFromText(String text)
34 | {
35 | return (SchemeFile) PsiFileFactory.getInstance(getProject())
36 | .createFileFromText(DUMMY + SchemeFileType.SCHEME_FILE_TYPE.getDefaultExtension(), text);
37 | }
38 |
39 | @Override
40 | public boolean hasSyntacticalErrors(@NotNull String text)
41 | {
42 | SchemeFile schemeFile = (SchemeFile) PsiFileFactory.getInstance(getProject())
43 | .createFileFromText(DUMMY + SchemeFileType.SCHEME_FILE_TYPE.getDefaultExtension(), text);
44 | return hasSyntacticalErrors(schemeFile);
45 | }
46 |
47 | @Override
48 | public boolean hasSyntacticalErrors(@NotNull PsiElement element)
49 | {
50 | if ((element instanceof PsiErrorElement))
51 | {
52 | return true;
53 | }
54 | for (PsiElement child : element.getChildren())
55 | {
56 | if (hasSyntacticalErrors(child))
57 | {
58 | return true;
59 | }
60 | }
61 | return false;
62 | }
63 |
64 | public Project getProject()
65 | {
66 | return project;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/dk/brics/automaton/AutomatonProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * dk.brics.automaton
3 | *
4 | * Copyright (c) 2001-2009 Anders Moeller
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without
8 | * modification, are permitted provided that the following conditions
9 | * are met:
10 | * 1. Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * 2. Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | * 3. The name of the author may not be used to endorse or promote products
16 | * derived from this software without specific prior written permission.
17 | *
18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 | */
29 |
30 | package dk.brics.automaton;
31 |
32 | import java.io.IOException;
33 |
34 | /**
35 | * Automaton provider for RegExp.{@link RegExp#toAutomaton(AutomatonProvider)}
36 | */
37 | public interface AutomatonProvider {
38 |
39 | /**
40 | * Returns automaton of the given name.
41 | * @param name automaton name
42 | * @return automaton
43 | * @throws IOException if errors occur
44 | */
45 | public Automaton getAutomaton(String name) throws IOException;
46 | }
47 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/schemely/findUsages/SchemeFindUsagesProvider.java:
--------------------------------------------------------------------------------
1 | package schemely.findUsages;
2 |
3 | import com.intellij.lang.cacheBuilder.DefaultWordsScanner;
4 | import com.intellij.lang.cacheBuilder.WordsScanner;
5 | import com.intellij.lang.findUsages.FindUsagesProvider;
6 | import com.intellij.psi.PsiElement;
7 | import org.jetbrains.annotations.NotNull;
8 | import org.jetbrains.annotations.Nullable;
9 | import schemely.lexer.SchemeLexer;
10 | import schemely.lexer.Tokens;
11 | import schemely.psi.impl.symbols.SchemeIdentifier;
12 |
13 |
14 | public class SchemeFindUsagesProvider implements FindUsagesProvider
15 | {
16 | @Nullable
17 | public WordsScanner getWordsScanner()
18 | {
19 | return new DefaultWordsScanner(new SchemeLexer(), Tokens.IDENTIFIERS, Tokens.COMMENTS, Tokens.STRINGS);
20 | }
21 |
22 | public boolean canFindUsagesFor(@NotNull PsiElement psiElement)
23 | {
24 | return psiElement instanceof SchemeIdentifier;
25 | }
26 |
27 | public String getHelpId(@NotNull PsiElement psiElement)
28 | {
29 | return null;
30 | }
31 |
32 | @NotNull
33 | public String getType(@NotNull PsiElement element)
34 | {
35 | if (element instanceof SchemeIdentifier)
36 | {
37 | return "symbol";
38 | }
39 | // if (element instanceof ClDef)
40 | // {
41 | // return "definition";
42 | // }
43 | return "entity";
44 | }
45 |
46 | @NotNull
47 | public String getDescriptiveName(@NotNull PsiElement element)
48 | {
49 | if (element instanceof SchemeIdentifier)
50 | {
51 | SchemeIdentifier symbol = (SchemeIdentifier) element;
52 | String name = symbol.getText();
53 | return name == null ? symbol.getText() : name;
54 | }
55 |
56 | return element.getText();
57 | }
58 |
59 | @NotNull
60 | public String getNodeText(@NotNull PsiElement element, boolean useFullName)
61 | {
62 | if (element instanceof SchemeIdentifier)
63 | {
64 | SchemeIdentifier symbol = (SchemeIdentifier) element;
65 | String name = symbol.getReferenceName();
66 | return name == null ? symbol.getText() : name;
67 | }
68 |
69 | return element.getText();
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/schemely/repl/toolwindow/actions/HistoryNextAction.java:
--------------------------------------------------------------------------------
1 | package schemely.repl.toolwindow.actions;
2 |
3 | import schemely.repl.ConsoleHistoryModel;
4 | import com.intellij.openapi.actionSystem.AnActionEvent;
5 | import com.intellij.openapi.actionSystem.EmptyAction;
6 | import com.intellij.openapi.application.ApplicationManager;
7 | import com.intellij.openapi.project.DumbAwareAction;
8 | import com.intellij.openapi.util.IconLoader;
9 | import schemely.repl.SchemeConsole;
10 | import schemely.scheme.REPL;
11 |
12 | import javax.swing.*;
13 |
14 | /**
15 | * @author Colin Fleming
16 | */
17 | public class HistoryNextAction extends DumbAwareAction
18 | {
19 | private static final Icon ACTIONS_NEXT_ICON = IconLoader.getIcon("/actions/nextOccurence.png");
20 | private static final String HISTORY_NEXT_ID = "Scheme.REPL.History.Next";
21 |
22 | private final SchemeConsole console;
23 |
24 | public HistoryNextAction(SchemeConsole console)
25 | {
26 | super(null, null, ACTIONS_NEXT_ICON);
27 | this.console = console;
28 | EmptyAction.setupAction(this, HISTORY_NEXT_ID, null);
29 | }
30 |
31 | @Override
32 | public void update(AnActionEvent e)
33 | {
34 | REPL repl = console.getConsoleEditor().getUserData(REPL.REPL_KEY);
35 | if (repl != null)
36 | {
37 | boolean active = repl.isActive();
38 | ConsoleHistoryModel model = console.getHistoryModel();
39 | active = active && model.hasNextHistory();
40 | e.getPresentation().setEnabled(active);
41 | }
42 | }
43 |
44 | @Override
45 | public void actionPerformed(AnActionEvent e)
46 | {
47 | ConsoleHistoryModel model = console.getHistoryModel();
48 | final String prev = model.getHistoryNext();
49 | ApplicationManager.getApplication().runWriteAction(new Runnable()
50 | {
51 | @Override
52 | public void run()
53 | {
54 | if (prev == null)
55 | {
56 | console.restoreCurrentREPLItem();
57 | }
58 | else
59 | {
60 | console.getEditorDocument().setText(prev);
61 | console.getCurrentEditor().getCaretModel().moveToOffset(prev.length());
62 | }
63 | }
64 | });
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/schemely/repl/toolwindow/actions/HistoryPreviousAction.java:
--------------------------------------------------------------------------------
1 | package schemely.repl.toolwindow.actions;
2 |
3 | import schemely.repl.ConsoleHistoryModel;
4 | import com.intellij.openapi.actionSystem.AnActionEvent;
5 | import com.intellij.openapi.actionSystem.EmptyAction;
6 | import com.intellij.openapi.application.ApplicationManager;
7 | import com.intellij.openapi.project.DumbAwareAction;
8 | import com.intellij.openapi.util.IconLoader;
9 | import schemely.repl.SchemeConsole;
10 | import schemely.scheme.REPL;
11 |
12 | import javax.swing.*;
13 |
14 | /**
15 | * @author Colin Fleming
16 | */
17 | public class HistoryPreviousAction extends DumbAwareAction
18 | {
19 | private static final Icon ACTIONS_PREVIOUS_ICON = IconLoader.getIcon("/actions/previousOccurence.png");
20 | private static final String HISTORY_PREVIOUS_ID = "Scheme.REPL.History.Previous";
21 |
22 | private final SchemeConsole console;
23 |
24 | public HistoryPreviousAction(SchemeConsole console)
25 | {
26 | super(null, null, ACTIONS_PREVIOUS_ICON);
27 | this.console = console;
28 | EmptyAction.setupAction(this, HISTORY_PREVIOUS_ID, null);
29 | }
30 |
31 | @Override
32 | public void update(AnActionEvent e)
33 | {
34 | REPL repl = console.getConsoleEditor().getUserData(REPL.REPL_KEY);
35 | if (repl != null)
36 | {
37 | boolean active = repl.isActive();
38 | ConsoleHistoryModel model = console.getHistoryModel();
39 | active = active && model.hasPreviousHistory();
40 | e.getPresentation().setEnabled(active);
41 | }
42 | }
43 |
44 | @Override
45 | public void actionPerformed(AnActionEvent e)
46 | {
47 | ConsoleHistoryModel model = console.getHistoryModel();
48 | if (model.isEditingCurrentItem())
49 | {
50 | console.saveCurrentREPLItem();
51 | }
52 |
53 | final String next = model.getHistoryPrev();
54 | ApplicationManager.getApplication().runWriteAction(new Runnable()
55 | {
56 | @Override
57 | public void run()
58 | {
59 | console.getEditorDocument().setText(next == null ? "" : next);
60 | console.getCurrentEditor().getCaretModel().moveToOffset(next == null ? 0 : next.length());
61 | }
62 | });
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/schemely.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/test/schemely/scheme/sisc/StreamTest.java:
--------------------------------------------------------------------------------
1 | package schemely.scheme.sisc;
2 |
3 | import junit.framework.TestCase;
4 |
5 | import java.io.ByteArrayOutputStream;
6 | import java.io.IOException;
7 | import java.nio.charset.Charset;
8 | import java.util.Arrays;
9 | import java.util.concurrent.atomic.AtomicInteger;
10 |
11 | /**
12 | * @author Colin Fleming
13 | */
14 | public class StreamTest extends TestCase
15 | {
16 | public static final Charset charset = Charset.defaultCharset();
17 | public static final String[] lines = new String[]{"`Twas brillig, and the slithy toves\n",
18 | " Did gyre and gimble in the wabe:\n",
19 | "All mimsy were the borogoves,\n",
20 | " And the mome raths outgrabe."};
21 | public static final String text = lines[0] + lines[1] + lines[2] + lines[3];
22 | public static final byte[] bytes = text.getBytes(charset);
23 |
24 |
25 | // TODO test block methods
26 | public void testInputStream() throws IOException
27 | {
28 | SISCInProcessREPL.ToReplInputStream inputStream = new SISCInProcessREPL.ToReplInputStream(charset);
29 |
30 | for (String line : lines)
31 | {
32 | inputStream.enqueue(line);
33 | }
34 | ByteArrayOutputStream output = new ByteArrayOutputStream();
35 | while (output.size() < bytes.length)
36 | {
37 | output.write(inputStream.read());
38 | }
39 |
40 | byte[] outputBytes = output.toByteArray();
41 | assertTrue(Arrays.equals(bytes, outputBytes));
42 | }
43 |
44 | // TODO test block methods
45 | public void testOutputStream() throws IOException
46 | {
47 | final AtomicInteger cursor = new AtomicInteger(0);
48 |
49 | SISCInProcessREPL.FromREPLOutputStream outputStream = new SISCInProcessREPL.FromREPLOutputStream(charset)
50 | {
51 | @Override
52 | protected void textAvailable(String text)
53 | {
54 | assertEquals(lines[cursor.getAndIncrement()], text);
55 | }
56 |
57 | public void check()
58 | {
59 | }
60 | };
61 |
62 | for (byte b : bytes)
63 | {
64 | outputStream.write(b);
65 | }
66 | outputStream.flush();
67 |
68 | assertEquals(lines.length, cursor.get());
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/schemely/psi/impl/SchemePsiElementBase.java:
--------------------------------------------------------------------------------
1 | package schemely.psi.impl;
2 |
3 | import com.intellij.extapi.psi.ASTWrapperPsiElement;
4 | import com.intellij.lang.ASTNode;
5 | import com.intellij.psi.PsiComment;
6 | import com.intellij.psi.PsiElement;
7 | import com.intellij.psi.PsiWhiteSpace;
8 | import com.intellij.psi.impl.source.tree.LeafPsiElement;
9 | import org.jetbrains.annotations.NotNull;
10 | import schemely.psi.api.SchemePsiElement;
11 |
12 |
13 | public abstract class SchemePsiElementBase extends ASTWrapperPsiElement implements SchemePsiElement
14 | {
15 | final private String name;
16 |
17 | public SchemePsiElementBase(@NotNull ASTNode astNode, String name)
18 | {
19 | super(astNode);
20 | this.name = name;
21 | }
22 |
23 | public static boolean isWrongElement(PsiElement element)
24 | {
25 | return element == null ||
26 | (element instanceof LeafPsiElement || element instanceof PsiWhiteSpace || element instanceof PsiComment);
27 | }
28 |
29 | public PsiElement getFirstNonLeafElement()
30 | {
31 | PsiElement first = getFirstChild();
32 | while (first != null && isWrongElement(first))
33 | {
34 | first = first.getNextSibling();
35 | }
36 | return first;
37 | }
38 |
39 | public PsiElement getLastNonLeafElement()
40 | {
41 | PsiElement lastChild = getLastChild();
42 | while (lastChild != null && isWrongElement(lastChild))
43 | {
44 | lastChild = lastChild.getPrevSibling();
45 | }
46 | return lastChild;
47 | }
48 |
49 | public T findFirstChildByClass(Class aClass)
50 | {
51 | PsiElement element = getFirstChild();
52 | while (element != null && !aClass.isInstance(element))
53 | {
54 | element = element.getNextSibling();
55 | }
56 | return aClass.cast(element);
57 | }
58 |
59 | public T findFirstSiblingByClass(Class aClass)
60 | {
61 | PsiElement element = getNextSibling();
62 | while (element != null && !aClass.isInstance(element))
63 | {
64 | element = element.getNextSibling();
65 | }
66 | return aClass.cast(element);
67 | }
68 |
69 | @Override
70 | public String toString()
71 | {
72 | return name == null ? super.toString() : name;
73 | }
74 |
75 | @Override
76 | public int getQuotingLevel()
77 | {
78 | return 0;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/schemely/repl/ConsoleHistoryModel.java:
--------------------------------------------------------------------------------
1 | package schemely.repl;
2 |
3 | import net.jcip.annotations.GuardedBy;
4 | import org.jetbrains.annotations.Nullable;
5 |
6 | import java.util.LinkedList;
7 |
8 | /**
9 | * Copied from IDEA core and heavily modified.
10 | *
11 | * @author Colin Fleming
12 | * @author Gregory.Shrago
13 | */
14 | public class ConsoleHistoryModel
15 | {
16 | public static final int DEFAULT_MAX_SIZE = 100;
17 |
18 | @GuardedBy("history")
19 | private int historyCursor = -1;
20 | @GuardedBy("history")
21 | private int maxHistorySize = DEFAULT_MAX_SIZE;
22 | @GuardedBy("history")
23 | private final LinkedList history = new LinkedList();
24 |
25 |
26 | public boolean isEditingCurrentItem()
27 | {
28 | synchronized (history)
29 | {
30 | return historyCursor == -1;
31 | }
32 | }
33 |
34 | public void addToHistory(String statement)
35 | {
36 | synchronized (history)
37 | {
38 | historyCursor = -1;
39 | history.remove(statement);
40 | if (history.size() >= maxHistorySize)
41 | {
42 | history.removeLast();
43 | }
44 | history.addFirst(statement);
45 | }
46 | }
47 |
48 | @Nullable
49 | public String getHistoryPrev()
50 | {
51 | synchronized (history)
52 | {
53 | if (historyCursor < history.size() - 1)
54 | {
55 | return history.get(++historyCursor);
56 | }
57 | else
58 | {
59 | return null;
60 | }
61 | }
62 | }
63 |
64 | @Nullable
65 | public String getHistoryNext()
66 | {
67 | synchronized (history)
68 | {
69 | if (historyCursor > 0)
70 | {
71 | return history.get(--historyCursor);
72 | }
73 | else
74 | {
75 | if (historyCursor == 0)
76 | {
77 | historyCursor--;
78 | }
79 | return null;
80 | }
81 | }
82 | }
83 |
84 | public boolean hasPreviousHistory()
85 | {
86 | synchronized (history)
87 | {
88 | return historyCursor < history.size() - 1;
89 | }
90 | }
91 |
92 | public boolean hasNextHistory()
93 | {
94 | synchronized (history)
95 | {
96 | return historyCursor >= 0;
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/schemely/psi/impl/symbols/CompleteSymbol.java:
--------------------------------------------------------------------------------
1 | package schemely.psi.impl.symbols;
2 |
3 | import com.intellij.codeInsight.lookup.LookupElement;
4 | import com.intellij.codeInsight.lookup.LookupElementBuilder;
5 | import com.intellij.psi.PsiElement;
6 | import com.intellij.psi.PsiFile;
7 | import com.intellij.psi.PsiNamedElement;
8 | import com.intellij.psi.ResolveState;
9 | import schemely.psi.resolve.SchemeResolveResult;
10 | import schemely.psi.resolve.completion.CompletionProcessor;
11 | import schemely.scheme.REPL;
12 |
13 | import java.util.HashMap;
14 | import java.util.Map;
15 |
16 |
17 | public class CompleteSymbol
18 | {
19 | public static Object[] getVariants(PsiElement symbol)
20 | {
21 | PsiElement lastParent = null;
22 | PsiElement current = symbol;
23 | CompletionProcessor processor = new CompletionProcessor();
24 | while (current != null)
25 | {
26 | if (!current.processDeclarations(processor, ResolveState.initial(), lastParent, symbol))
27 | {
28 | break;
29 | }
30 | lastParent = current;
31 | current = current.getContext();
32 | }
33 |
34 | SchemeResolveResult[] candidates = processor.getCandidates();
35 | if (candidates.length == 0)
36 | {
37 | return PsiNamedElement.EMPTY_ARRAY;
38 | }
39 |
40 | Map variants = new HashMap();
41 |
42 | for (SchemeResolveResult candidate : candidates)
43 | {
44 | PsiNamedElement element = candidate.getElement();
45 | variants.put(element.getName(), mapToLookupElement(element));
46 | }
47 |
48 | PsiFile file = symbol.getContainingFile();
49 | REPL repl = file.getCopyableUserData(REPL.REPL_KEY);
50 | if (repl != null)
51 | {
52 | for (PsiNamedElement namedElement : repl.getSymbolVariants(symbol.getManager(), symbol))
53 | {
54 | variants.put(namedElement.getName(), mapToLookupElement(namedElement));
55 | }
56 | }
57 |
58 | return variants.values().toArray(new Object[variants.size()]);
59 | }
60 |
61 | private static LookupElement mapToLookupElement(PsiElement element)
62 | {
63 | if (element instanceof PsiNamedElement)
64 | {
65 | return LookupElementBuilder.create((PsiNamedElement) element);
66 | }
67 | return LookupElementBuilder.create(element, element.getText());
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/schemely/actions/NewSchemeFileAction.java:
--------------------------------------------------------------------------------
1 | package schemely.actions;
2 |
3 | import com.intellij.psi.PsiDirectory;
4 | import com.intellij.psi.PsiElement;
5 | import com.intellij.psi.PsiFile;
6 | import com.intellij.psi.PsiFileFactory;
7 | import com.intellij.openapi.project.Project;
8 | import org.jetbrains.annotations.NotNull;
9 | import schemely.SchemeBundle;
10 | import schemely.SchemeIcons;
11 | import schemely.file.SchemeFileType;
12 | import schemely.lexer.Tokens;
13 |
14 |
15 | public class NewSchemeFileAction extends NewSchemeActionBase
16 | {
17 | private static final String DUMMY = "dummy.";
18 |
19 | public NewSchemeFileAction()
20 | {
21 | super(SchemeBundle.message("newfile.menu.action.text"),
22 | SchemeBundle.message("newfile.menu.action.description"),
23 | SchemeIcons.SCHEME_ICON);
24 | }
25 |
26 | protected String getActionName(PsiDirectory directory, String newName)
27 | {
28 | return SchemeBundle.message("newfile.menu.action.text");
29 | }
30 |
31 | protected String getDialogPrompt()
32 | {
33 | return SchemeBundle.message("newfile.dlg.prompt");
34 | }
35 |
36 | protected String getDialogTitle()
37 | {
38 | return SchemeBundle.message("newfile.dlg.title");
39 | }
40 |
41 | protected String getCommandName()
42 | {
43 | return SchemeBundle.message("newfile.command.name");
44 | }
45 |
46 | @NotNull
47 | protected PsiElement[] doCreate(String newName, PsiDirectory directory) throws Exception
48 | {
49 | PsiFile file = createFileFromTemplate(directory, newName, "SchemeFile.scm");
50 | PsiElement lastChild = file.getLastChild();
51 | Project project = directory.getProject();
52 | if (lastChild != null && lastChild.getNode() != null && lastChild.getNode().getElementType() != Tokens.WHITESPACE)
53 | {
54 | file.add(createWhiteSpace(project));
55 | }
56 | file.add(createWhiteSpace(project));
57 | PsiElement child = file.getLastChild();
58 | return child != null ? new PsiElement[]{file, child} : new PsiElement[]{file};
59 | }
60 |
61 | private static PsiElement createWhiteSpace(Project project)
62 | {
63 | PsiFile
64 | dummyFile =
65 | PsiFileFactory.getInstance(project)
66 | .createFileFromText(DUMMY + SchemeFileType.SCHEME_FILE_TYPE.getDefaultExtension(), "\n");
67 | return dummyFile.getFirstChild();
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/test/schemely/parser/SISCParserTest.java:
--------------------------------------------------------------------------------
1 | package schemely.parser;
2 |
3 | import com.intellij.openapi.vfs.JarFileSystem;
4 | import com.intellij.openapi.vfs.VfsUtil;
5 | import com.intellij.openapi.vfs.VirtualFile;
6 | import com.intellij.openapi.vfs.VirtualFileManager;
7 | import com.intellij.psi.PsiFile;
8 | import com.intellij.psi.PsiManager;
9 | import org.testng.annotations.DataProvider;
10 | import org.testng.annotations.Test;
11 | import schemely.file.SchemeFileType;
12 | import schemely.psi.util.SchemePsiUtil;
13 | import schemely.scheme.sisc.SISCConfigUtil;
14 |
15 | import java.util.ArrayList;
16 | import java.util.List;
17 |
18 | /**
19 | * @author Colin Fleming
20 | */
21 | public class SISCParserTest extends ParserTestBase
22 | {
23 | @Test(dataProvider = "siscFiles", groups = "Schemely")
24 | public void test(PsiFileWrapper wrapper)
25 | {
26 | assert !SchemePsiUtil.containsSyntaxErrors(wrapper.psiFile);
27 | }
28 |
29 | @DataProvider(name = "siscFiles")
30 | private Object[][] getSISCFiles()
31 | {
32 | setUp();
33 |
34 | String url = VfsUtil.pathToUrl(SISCConfigUtil.SISC_SRC);
35 | VirtualFile sdkFile = VirtualFileManager.getInstance().findFileByUrl(url);
36 | VirtualFile jarFile = JarFileSystem.getInstance().getJarRootForLocalFile(sdkFile);
37 |
38 | List files = new ArrayList();
39 | parseAll(jarFile, files);
40 |
41 | Object[][] ret = new Object[files.size()][];
42 | for (int i = 0; i < files.size(); i++)
43 | {
44 | ret[i] = new Object[] { new PsiFileWrapper(files.get(i)) };
45 | }
46 | return ret;
47 |
48 | }
49 |
50 | private void parseAll(VirtualFile file, List files)
51 | {
52 | if (file.isDirectory())
53 | {
54 | for (VirtualFile child : file.getChildren())
55 | {
56 | parseAll(child, files);
57 | }
58 | }
59 | else if (file.getFileType() == SchemeFileType.SCHEME_FILE_TYPE)
60 | {
61 | PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
62 | files.add(psiFile);
63 | }
64 | }
65 |
66 | private static class PsiFileWrapper
67 | {
68 | private final PsiFile psiFile;
69 |
70 | public PsiFileWrapper(PsiFile psiFile)
71 | {
72 | this.psiFile = psiFile;
73 | }
74 |
75 | @Override
76 | public String toString()
77 | {
78 | return psiFile.getName();
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/schemely/lexer/Tokens.java:
--------------------------------------------------------------------------------
1 | package schemely.lexer;
2 |
3 | import com.intellij.psi.TokenType;
4 | import com.intellij.psi.tree.IElementType;
5 | import com.intellij.psi.tree.TokenSet;
6 | import schemely.parser.SchemeElementType;
7 |
8 | public interface Tokens
9 | {
10 | // Special characters
11 | IElementType OPEN_VECTOR = new SchemeElementType("#(");
12 | IElementType LEFT_PAREN = new SchemeElementType("(");
13 | IElementType RIGHT_PAREN = new SchemeElementType(")");
14 |
15 | IElementType LEFT_CURLY = new SchemeElementType("{");
16 | IElementType RIGHT_CURLY = new SchemeElementType("}");
17 |
18 | IElementType LEFT_SQUARE = new SchemeElementType("[");
19 | IElementType RIGHT_SQUARE = new SchemeElementType("]");
20 |
21 | IElementType QUOTE_MARK = new SchemeElementType("'");
22 | IElementType BACKQUOTE = new SchemeElementType("`");
23 | IElementType COMMA = new SchemeElementType(",");
24 | IElementType COMMA_AT = new SchemeElementType(",@");
25 |
26 | // Comments
27 | IElementType COMMENT = new SchemeElementType("comment");
28 | IElementType BLOCK_COMMENT = new SchemeElementType("block comment");
29 |
30 | TokenSet COMMENTS = TokenSet.create(COMMENT, BLOCK_COMMENT);
31 |
32 | // Literals
33 | IElementType STRING_LITERAL = new SchemeElementType("string literal");
34 | IElementType NUMBER_LITERAL = new SchemeElementType("number literal");
35 | IElementType CHAR_LITERAL = new SchemeElementType("character literal");
36 | IElementType BOOLEAN_LITERAL = new SchemeElementType("boolean literal");
37 |
38 | TokenSet LITERALS = TokenSet.create(STRING_LITERAL, NUMBER_LITERAL, CHAR_LITERAL, BOOLEAN_LITERAL);
39 |
40 | IElementType IDENTIFIER = new SchemeElementType("identifier");
41 |
42 | IElementType DOT = new SchemeElementType(".");
43 |
44 | IElementType SPECIAL = new SchemeElementType("special");
45 |
46 | // Control characters
47 | IElementType WHITESPACE = TokenType.WHITE_SPACE;
48 | IElementType BAD_CHARACTER = TokenType.BAD_CHARACTER;
49 |
50 | // Useful token sets
51 | TokenSet WHITESPACE_SET = TokenSet.create(WHITESPACE);
52 | TokenSet IDENTIFIERS = TokenSet.create(IDENTIFIER);
53 | TokenSet STRINGS = TokenSet.create(STRING_LITERAL);
54 |
55 | TokenSet PREFIXES = TokenSet.create(QUOTE_MARK, BACKQUOTE, COMMA, COMMA_AT);
56 | TokenSet BRACES = TokenSet.create(LEFT_PAREN, LEFT_CURLY, LEFT_SQUARE, RIGHT_PAREN, RIGHT_CURLY, RIGHT_SQUARE);
57 | TokenSet OPEN_BRACES = TokenSet.create(LEFT_PAREN, LEFT_CURLY, LEFT_SQUARE);
58 | }
59 |
--------------------------------------------------------------------------------
/src/schemely/psi/stubs/elements/SchemeStubFileElementType.java:
--------------------------------------------------------------------------------
1 | package schemely.psi.stubs.elements;
2 |
3 | import com.intellij.psi.StubBuilder;
4 | import com.intellij.psi.stubs.*;
5 | import com.intellij.psi.tree.IStubFileElementType;
6 | import com.intellij.util.io.StringRef;
7 | import schemely.file.SchemeFileType;
8 | import schemely.psi.stubs.SchemeFileStubBuilder;
9 | import schemely.psi.stubs.api.SchemeFileStub;
10 | import schemely.psi.stubs.impl.SchemeFileStubImpl;
11 | import schemely.psi.stubs.index.SchemeClassNameIndex;
12 | import schemely.psi.stubs.index.SchemeFullScriptNameIndex;
13 |
14 | import java.io.IOException;
15 |
16 |
17 | public class SchemeStubFileElementType extends IStubFileElementType
18 | {
19 | private static final int CACHES_VERSION = 10;
20 |
21 | public SchemeStubFileElementType()
22 | {
23 | super(SchemeFileType.SCHEME_LANGUAGE);
24 | }
25 |
26 | public StubBuilder getBuilder()
27 | {
28 | return new SchemeFileStubBuilder();
29 | }
30 |
31 | @Override
32 | public int getStubVersion()
33 | {
34 | return super.getStubVersion() + CACHES_VERSION;
35 | }
36 |
37 | public String getExternalId()
38 | {
39 | return "scheme.FILE";
40 | }
41 |
42 | @Override
43 | public void indexStub(PsiFileStub stub, IndexSink sink)
44 | {
45 | super.indexStub(stub, sink);
46 | }
47 |
48 | @Override
49 | public void serialize(SchemeFileStub stub, StubOutputStream dataStream) throws IOException
50 | {
51 | dataStream.writeName(stub.getPackageName().toString());
52 | dataStream.writeName(stub.getName().toString());
53 | dataStream.writeBoolean(stub.isClassDefinition());
54 | }
55 |
56 | @Override
57 | public SchemeFileStub deserialize(StubInputStream dataStream, StubElement parentStub) throws IOException
58 | {
59 | StringRef packName = dataStream.readName();
60 | StringRef name = dataStream.readName();
61 | boolean isScript = dataStream.readBoolean();
62 | return new SchemeFileStubImpl(packName, name, isScript);
63 | }
64 |
65 | public void indexStub(SchemeFileStub stub, IndexSink sink)
66 | {
67 | String name = stub.getName().toString();
68 | if (stub.isClassDefinition() && name != null)
69 | {
70 | sink.occurrence(SchemeClassNameIndex.KEY, name);
71 | String pName = stub.getPackageName().toString();
72 | String fqn = pName == null || pName.length() == 0 ? name : pName + "." + name;
73 | sink.occurrence(SchemeFullScriptNameIndex.KEY, fqn.hashCode());
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/schemely/scheme/common/REPLUtil.java:
--------------------------------------------------------------------------------
1 | package schemely.scheme.common;
2 |
3 | import com.intellij.execution.CantRunException;
4 | import com.intellij.execution.configurations.CommandLineBuilder;
5 | import com.intellij.execution.configurations.GeneralCommandLine;
6 | import com.intellij.execution.configurations.JavaParameters;
7 | import com.intellij.ide.DataManager;
8 | import com.intellij.openapi.actionSystem.PlatformDataKeys;
9 | import com.intellij.openapi.module.Module;
10 | import com.intellij.openapi.project.Project;
11 | import com.intellij.openapi.projectRoots.JavaSdkType;
12 | import com.intellij.openapi.projectRoots.Sdk;
13 | import com.intellij.openapi.projectRoots.SdkType;
14 | import com.intellij.openapi.roots.ModuleRootManager;
15 | import com.intellij.openapi.roots.ModuleSourceOrderEntry;
16 | import com.intellij.openapi.roots.OrderEntry;
17 | import com.intellij.openapi.roots.OrderRootType;
18 | import com.intellij.openapi.vfs.VirtualFile;
19 |
20 | import java.util.ArrayList;
21 | import java.util.Arrays;
22 | import java.util.Collection;
23 | import java.util.HashSet;
24 | import java.util.List;
25 |
26 | /**
27 | * @author Colin Fleming
28 | */
29 | public class REPLUtil
30 | {
31 | public static void addSourcesToClasspath(Module module, JavaParameters params)
32 | {
33 | Collection virtualFiles = new HashSet();
34 | ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
35 | OrderEntry[] entries = moduleRootManager.getOrderEntries();
36 | for (OrderEntry orderEntry : entries)
37 | {
38 | if (orderEntry instanceof ModuleSourceOrderEntry)
39 | {
40 | virtualFiles.addAll(Arrays.asList(orderEntry.getFiles(OrderRootType.SOURCES)));
41 | }
42 | }
43 |
44 | for (VirtualFile file : virtualFiles)
45 | {
46 | params.getClassPath().add(file.getPath());
47 | }
48 | }
49 |
50 | public static List getCommandLine(JavaParameters params) throws CantRunException
51 | {
52 | Project project = PlatformDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext());
53 | GeneralCommandLine line = CommandLineBuilder.createFromJavaParameters(params, project, true);
54 |
55 | Sdk sdk = params.getJdk();
56 | assert sdk != null;
57 | SdkType type = sdk.getSdkType();
58 | String executablePath = ((JavaSdkType) type).getVMExecutablePath(sdk);
59 |
60 | List cmd = new ArrayList();
61 | cmd.add(executablePath);
62 | cmd.addAll(line.getParametersList().getList());
63 | return cmd;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/.idea/projectCodeStyle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/test/schemely/parser/ParseTestCaseBase.java:
--------------------------------------------------------------------------------
1 | package schemely.parser;
2 |
3 | import com.intellij.psi.PsiElement;
4 | import com.intellij.psi.PsiFile;
5 | import org.intellij.lang.annotations.Language;
6 | import org.testng.annotations.Test;
7 | import schemely.psi.impl.SchemeLiteral;
8 | import schemely.psi.impl.list.SchemeList;
9 | import schemely.psi.impl.symbols.SchemeIdentifier;
10 |
11 | /**
12 | * @author Colin Fleming
13 | */
14 | public class ParseTestCaseBase extends ParserTestBase
15 | {
16 | @Test(dataProvider = "parseFiles", groups = "Schemely")
17 | public void parseTest(ParseTestCase testCase)
18 | {
19 | PsiFile psiFile = parse(testCase.contents);
20 | PsiElement[] children = psiFile.getChildren();
21 | assert children.length == 1 : "Expecting 1 child, found " + children.length;
22 | PsiElement child = children[0];
23 | assert testCase.theClass.isAssignableFrom(child.getClass()) :
24 | "Expected " + testCase.theClass.getName() + ", found " + child.getClass().getName();
25 | testCase.extraChecks(child);
26 | }
27 |
28 | protected ParseTestCaseBase.ParseTestCase list(@Language("Scheme") String contents)
29 | {
30 | return element(contents, SchemeList.class);
31 | }
32 |
33 |
34 | protected ParseTestCaseBase.ParseTestCase improperList(@Language("Scheme") String contents)
35 | {
36 | return new ParseTestCaseBase.ParseTestCase(contents, SchemeList.class)
37 | {
38 | @Override
39 | protected void extraChecks(PsiElement element)
40 | {
41 | assert ((SchemeList) element).isImproper() : "Expected improper list";
42 | }
43 | };
44 | }
45 |
46 | protected ParseTestCase literal(@Language("Scheme") String contents)
47 | {
48 | return element(contents, SchemeLiteral.class);
49 | }
50 |
51 | protected ParseTestCase identifier(@Language("Scheme") String contents)
52 | {
53 | return element(contents, SchemeIdentifier.class);
54 | }
55 |
56 | protected ParseTestCase element(@Language("Scheme") String contents, Class theClass)
57 | {
58 | return new ParseTestCase(contents, theClass);
59 | }
60 |
61 | public static class ParseTestCase
62 | {
63 | public final String contents;
64 | public final Class extends PsiElement> theClass;
65 |
66 | public ParseTestCase(String contents, Class extends PsiElement> theClass)
67 | {
68 | this.contents = contents;
69 | this.theClass = theClass;
70 | }
71 |
72 | protected void extraChecks(PsiElement element)
73 | {
74 | }
75 |
76 | @Override
77 | public String toString()
78 | {
79 | return contents;
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | http://www.w3.org/1999/xhtml
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/src/schemely/actions/SchemeTemplatesFactory.java:
--------------------------------------------------------------------------------
1 | package schemely.actions;
2 |
3 | import com.intellij.ide.fileTemplates.*;
4 | import com.intellij.psi.PsiDirectory;
5 | import com.intellij.psi.PsiFile;
6 | import com.intellij.psi.PsiFileFactory;
7 | import com.intellij.util.IncorrectOperationException;
8 | import org.jetbrains.annotations.NonNls;
9 | import schemely.SchemeBundle;
10 | import schemely.SchemeIcons;
11 |
12 | import java.util.Properties;
13 |
14 |
15 | public class SchemeTemplatesFactory implements FileTemplateGroupDescriptorFactory
16 | {
17 | @NonNls
18 | private static final String SCHEME_FILE = "SchemeFile.scm";
19 | @NonNls
20 | static final String NAME_TEMPLATE_PROPERTY = "NAME";
21 | @NonNls
22 | static final String LOW_CASE_NAME_TEMPLATE_PROPERTY = "lowCaseName";
23 |
24 |
25 | public FileTemplateGroupDescriptor getFileTemplatesDescriptor()
26 | {
27 | FileTemplateGroupDescriptor
28 | group =
29 | new FileTemplateGroupDescriptor(SchemeBundle.message("file.template.group.title.scheme"),
30 | SchemeIcons.SCHEME_ICON);
31 | group.addTemplate(new FileTemplateDescriptor(SCHEME_FILE, SchemeIcons.SCHEME_ICON));
32 | return group;
33 | }
34 |
35 | public static PsiFile createFromTemplate(PsiDirectory directory,
36 | String name,
37 | String fileName,
38 | String templateName,
39 | @NonNls String... parameters) throws IncorrectOperationException
40 | {
41 | FileTemplate template = FileTemplateManager.getInstance().getInternalTemplate(templateName);
42 | Properties properties = new Properties(FileTemplateManager.getInstance().getDefaultProperties());
43 | JavaTemplateUtil.setPackageNameAttribute(properties, directory);
44 | properties.setProperty(NAME_TEMPLATE_PROPERTY, name);
45 | properties.setProperty(LOW_CASE_NAME_TEMPLATE_PROPERTY, name.substring(0, 1).toLowerCase() + name.substring(1));
46 | for (int i = 0; i < parameters.length; i += 2)
47 | {
48 | properties.setProperty(parameters[i], parameters[i + 1]);
49 | }
50 | String text;
51 | try
52 | {
53 | text = template.getText(properties);
54 | }
55 | catch (Exception e)
56 | {
57 | throw new RuntimeException("Unable to load template for " +
58 | FileTemplateManager.getInstance().internalTemplateToSubject(templateName), e);
59 | }
60 |
61 | PsiFileFactory factory = PsiFileFactory.getInstance(directory.getProject());
62 | PsiFile file = factory.createFileFromText(fileName, text);
63 | return (PsiFile) directory.add(file);
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/src/schemely/SchemeFoldingBuilder.java:
--------------------------------------------------------------------------------
1 | package schemely;
2 |
3 | import com.intellij.lang.ASTNode;
4 | import com.intellij.lang.folding.FoldingBuilder;
5 | import com.intellij.lang.folding.FoldingDescriptor;
6 | import com.intellij.openapi.editor.Document;
7 | import com.intellij.psi.PsiElement;
8 | import com.intellij.psi.tree.IElementType;
9 | import schemely.parser.AST;
10 | import static schemely.parser.AST.LIST;
11 | import schemely.psi.impl.SchemeFile;
12 | import schemely.psi.impl.list.SchemeList;
13 |
14 | import java.util.ArrayList;
15 | import java.util.List;
16 |
17 | public class SchemeFoldingBuilder implements FoldingBuilder
18 | {
19 | public String getPlaceholderText(ASTNode node)
20 | {
21 | IElementType type = node.getElementType();
22 | PsiElement psi = node.getPsi();
23 | if (psi instanceof SchemeList)
24 | {
25 | String text = ((SchemeList) psi).getPresentableText();
26 | return "(" + (text != null ? text + " " : "") + "...)";
27 | }
28 | throw new Error("Unexpected node: " + type + "-->" + node.getText());
29 | }
30 |
31 | public boolean isCollapsedByDefault(ASTNode node)
32 | {
33 | return false;
34 | }
35 |
36 | public FoldingDescriptor[] buildFoldRegions(ASTNode node, Document document)
37 | {
38 | touchTree(node);
39 | List descriptors = new ArrayList();
40 | appendDescriptors(node, descriptors);
41 | return descriptors.toArray(new FoldingDescriptor[descriptors.size()]);
42 | }
43 |
44 | /**
45 | * We have to touch the PSI tree to get the folding to show up when we first open a file
46 | *
47 | * @param node given node
48 | */
49 | private void touchTree(ASTNode node)
50 | {
51 | if (node.getElementType() == AST.FILE)
52 | {
53 | node.getPsi().getFirstChild();
54 | }
55 | }
56 |
57 | private void appendDescriptors(ASTNode node, List descriptors)
58 | {
59 | if (isFoldableNode(node))
60 | {
61 | descriptors.add(new FoldingDescriptor(node, node.getTextRange()));
62 | }
63 |
64 | ASTNode child = node.getFirstChildNode();
65 | while (child != null)
66 | {
67 | appendDescriptors(child, descriptors);
68 | child = child.getTreeNext();
69 | }
70 | }
71 |
72 | private boolean isFoldableNode(ASTNode node)
73 | {
74 | PsiElement element = node.getPsi();
75 | IElementType type = node.getElementType();
76 | if (type == LIST &&
77 | element.getParent() instanceof SchemeFile &&
78 | node.getText().contains("\n") &&
79 | element instanceof SchemeList)
80 | {
81 | return true;
82 | }
83 |
84 | return false; // (type == IDENTIFIER || type == DEFMETHOD) && node.getText().contains("\n");
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/schemely/psi/resolve/ResolveUtil.java:
--------------------------------------------------------------------------------
1 | package schemely.psi.resolve;
2 |
3 | import com.intellij.codeInsight.completion.CompletionInitializationContext;
4 | import com.intellij.psi.PsiElement;
5 | import com.intellij.psi.PsiNamedElement;
6 | import com.intellij.psi.ResolveState;
7 | import com.intellij.psi.scope.NameHint;
8 | import com.intellij.psi.scope.PsiScopeProcessor;
9 | import org.jetbrains.annotations.NotNull;
10 | import schemely.psi.api.SchemePsiElement;
11 |
12 | import static schemely.psi.impl.SchemePsiElementBase.isWrongElement;
13 |
14 |
15 | public abstract class ResolveUtil
16 | {
17 | public static boolean resolve(PsiElement place, PsiScopeProcessor processor)
18 | {
19 | PsiElement lastParent = null;
20 | PsiElement current = place;
21 | while (current != null)
22 | {
23 | if (!current.processDeclarations(processor, ResolveState.initial(), lastParent, place))
24 | {
25 | return false;
26 | }
27 | lastParent = current;
28 | current = current.getContext();
29 | }
30 |
31 | return true;
32 | }
33 |
34 | public static boolean processElement(PsiScopeProcessor processor, PsiNamedElement namedElement)
35 | {
36 | if (namedElement == null)
37 | {
38 | return true;
39 | }
40 | NameHint nameHint = processor.getHint(NameHint.KEY);
41 | String name = nameHint == null ? null : nameHint.getName(ResolveState.initial());
42 | String elementName = namedElement.getName();
43 | if ((name == null || name.equals(elementName)) &&
44 | !elementName.endsWith(CompletionInitializationContext.DUMMY_IDENTIFIER_TRIMMED))
45 | {
46 | return processor.execute(namedElement, ResolveState.initial());
47 | }
48 | return true;
49 | }
50 |
51 | public static int getQuotingLevel(PsiElement place)
52 | {
53 | int ret = 0;
54 | PsiElement element = place;
55 | while (element != null)
56 | {
57 | if (element instanceof SchemePsiElement)
58 | {
59 | SchemePsiElement schemeElement = (SchemePsiElement) element;
60 | ret += schemeElement.getQuotingLevel();
61 | }
62 | element = element.getContext();
63 | }
64 | return ret;
65 | }
66 |
67 | public static PsiElement getNextNonLeafElement(@NotNull PsiElement element)
68 | {
69 | PsiElement next = element.getNextSibling();
70 | while ((next != null) && isWrongElement(next))
71 | {
72 | next = next.getNextSibling();
73 | }
74 | return next;
75 | }
76 |
77 | public static PsiElement getPrevNonLeafElement(@NotNull PsiElement element)
78 | {
79 | PsiElement next = element.getPrevSibling();
80 | while ((next != null) && isWrongElement(next))
81 | {
82 | next = next.getPrevSibling();
83 | }
84 | return next;
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/schemely/utils/SchemeConfigUtil.java:
--------------------------------------------------------------------------------
1 | package schemely.utils;
2 |
3 | import com.intellij.openapi.roots.OrderRootType;
4 | import com.intellij.openapi.roots.libraries.Library;
5 | import com.intellij.openapi.util.text.StringUtil;
6 | import com.intellij.openapi.vfs.VirtualFile;
7 |
8 | import java.io.File;
9 | import java.io.IOException;
10 | import java.util.jar.JarFile;
11 |
12 | /**
13 | * @author Colin Fleming
14 | */
15 | public class SchemeConfigUtil
16 | {
17 | public static boolean checkLibrary(Library library, String jarNamePrefix, String necessaryClass)
18 | {
19 | boolean result = false;
20 | VirtualFile[] classFiles = library.getFiles(OrderRootType.CLASSES);
21 | for (VirtualFile file : classFiles)
22 | {
23 | String path = file.getPath();
24 | if (path != null && "jar".equals(file.getExtension()))
25 | {
26 | path = StringUtil.trimEnd(path, "!/");
27 | String name = file.getName();
28 |
29 | File realFile = new File(path);
30 | if (realFile.exists())
31 | {
32 | try
33 | {
34 | JarFile jarFile = new JarFile(realFile);
35 | try
36 | {
37 | if (name.startsWith(jarNamePrefix))
38 | {
39 | result = jarFile.getJarEntry(necessaryClass) != null;
40 | }
41 | }
42 | finally
43 | {
44 | jarFile.close();
45 | }
46 | }
47 | catch (IOException ignore)
48 | {
49 | result = false;
50 | }
51 | }
52 | }
53 | }
54 | return result;
55 | }
56 |
57 | public static String getSpecificJarForLibrary(Library library, String jarNamePrefix, String necessaryClass)
58 | {
59 | VirtualFile[] classFiles = library.getFiles(OrderRootType.CLASSES);
60 | for (VirtualFile file : classFiles)
61 | {
62 | String path = file.getPath();
63 | if (path != null && "jar".equals(file.getExtension()))
64 | {
65 | path = StringUtil.trimEnd(path, "!/");
66 | String name = file.getName();
67 |
68 | File realFile = new File(path);
69 | if (realFile.exists())
70 | {
71 | try
72 | {
73 | JarFile jarFile = new JarFile(realFile);
74 | try
75 | {
76 | if (name.startsWith(jarNamePrefix) && jarFile.getJarEntry(necessaryClass) != null)
77 | {
78 | return path;
79 | }
80 | }
81 | finally
82 | {
83 | jarFile.close();
84 | }
85 | }
86 | catch (IOException ignored)
87 | {
88 | //do nothing
89 | }
90 | }
91 | }
92 | }
93 | return "";
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/src/schemely/psi/impl/list/SchemeListBase.java:
--------------------------------------------------------------------------------
1 | package schemely.psi.impl.list;
2 |
3 | import com.intellij.lang.ASTNode;
4 | import com.intellij.psi.PsiElement;
5 | import com.intellij.psi.impl.source.tree.LeafPsiElement;
6 | import org.jetbrains.annotations.NotNull;
7 | import org.jetbrains.annotations.Nullable;
8 | import schemely.lexer.Tokens;
9 | import schemely.psi.impl.SchemePsiElementBase;
10 | import schemely.psi.impl.symbols.SchemeIdentifier;
11 | import schemely.psi.util.SchemePsiUtil;
12 |
13 |
14 | public abstract class SchemeListBase extends SchemePsiElementBase
15 | {
16 | public SchemeListBase(@NotNull ASTNode astNode, String name)
17 | {
18 | super(astNode, name);
19 | }
20 |
21 | @Nullable
22 | public String getPresentableText()
23 | {
24 | SchemeIdentifier first = findChildByClass(SchemeIdentifier.class);
25 | if (first == null)
26 | {
27 | return null;
28 | }
29 | String text1 = getHeadText();
30 | PsiElement next = SchemePsiUtil.findNextSiblingByClass(first, SchemeIdentifier.class);
31 | if (next == null)
32 | {
33 | return text1;
34 | }
35 | else
36 | {
37 | return text1 + " " + next.getText();
38 | }
39 | }
40 |
41 | @Nullable
42 | public String getHeadText()
43 | {
44 | SchemeIdentifier first = findChildByClass(SchemeIdentifier.class);
45 | if (first == null)
46 | {
47 | return null;
48 | }
49 | return first.getText();
50 | }
51 |
52 | public boolean isImproper()
53 | {
54 | PsiElement dot = findChildByType(Tokens.DOT);
55 | return dot != null;
56 | }
57 |
58 | @Nullable
59 | public SchemeIdentifier getFirstIdentifier()
60 | {
61 | PsiElement child = getFirstChild();
62 | while (child instanceof LeafPsiElement)
63 | {
64 | child = child.getNextSibling();
65 | }
66 | if (child instanceof SchemeIdentifier)
67 | {
68 | return (SchemeIdentifier) child;
69 | }
70 | return null;
71 | }
72 |
73 | public PsiElement getSecondNonLeafElement()
74 | {
75 | PsiElement first = getFirstChild();
76 | while ((first != null) && isWrongElement(first))
77 | {
78 | first = first.getNextSibling();
79 | }
80 | if (first == null)
81 | {
82 | return null;
83 | }
84 |
85 | PsiElement second = first.getNextSibling();
86 | while (second != null && isWrongElement(second))
87 | {
88 | second = second.getNextSibling();
89 | }
90 | return second;
91 | }
92 |
93 | public SchemeIdentifier[] getAllIdentifiers()
94 | {
95 | return findChildrenByClass(SchemeIdentifier.class);
96 | }
97 |
98 | public SchemeList[] getSubLists()
99 | {
100 | return findChildrenByClass(SchemeList.class);
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/schemely/formatter/codeStyle/SchemeCodeStylePanel.java:
--------------------------------------------------------------------------------
1 | package schemely.formatter.codeStyle;
2 |
3 | import com.intellij.application.options.CodeStyleAbstractPanel;
4 | import com.intellij.openapi.editor.colors.EditorColorsScheme;
5 | import com.intellij.openapi.editor.highlighter.EditorHighlighter;
6 | import com.intellij.openapi.fileTypes.FileType;
7 | import com.intellij.psi.PsiFile;
8 | import com.intellij.psi.codeStyle.CodeStyleSettings;
9 | import org.jetbrains.annotations.NotNull;
10 | import schemely.file.SchemeFileType;
11 | import schemely.highlighter.SchemeEditorHighlighter;
12 |
13 | import javax.swing.*;
14 |
15 |
16 | public class SchemeCodeStylePanel extends CodeStyleAbstractPanel
17 | {
18 | private JPanel panel;
19 | private JPanel previewPanel;
20 | private JTextArea defineFormsTextArea;
21 | private JTabbedPane tabbedPane;
22 | private JPanel alignPanel;
23 |
24 | protected SchemeCodeStylePanel(CodeStyleSettings settings)
25 | {
26 | super(settings);
27 | SchemeCodeStyleSettings css = settings.getCustomSettings(SchemeCodeStyleSettings.class);
28 | setSettings(css);
29 | installPreviewPanel(previewPanel);
30 | }
31 |
32 | protected EditorHighlighter createHighlighter(EditorColorsScheme scheme)
33 | {
34 | return new SchemeEditorHighlighter(scheme);
35 | }
36 |
37 | protected int getRightMargin()
38 | {
39 | return 0;
40 | }
41 |
42 | protected void prepareForReformat(PsiFile psiFile)
43 | {
44 | }
45 |
46 | @NotNull
47 | protected FileType getFileType()
48 | {
49 | return SchemeFileType.SCHEME_FILE_TYPE;
50 | }
51 |
52 | protected String getPreviewText()
53 | {
54 | return "(print \"type = \" (or type \"!!YIKES!NO TYPE!!!\") \"$%$% \"\n" +
55 | " (if (= \"\"\n" +
56 | " text) \"!!NO TEXT!!!\" text))";
57 | }
58 |
59 | public void apply(CodeStyleSettings settings)
60 | {
61 | SchemeCodeStyleSettings scmSettings = settings.getCustomSettings(SchemeCodeStyleSettings.class);
62 | scmSettings.defineForms = defineFormsTextArea.getText();
63 | updatePreview();
64 | }
65 |
66 | public boolean isModified(CodeStyleSettings settings)
67 | {
68 | SchemeCodeStyleSettings scmSettings = settings.getCustomSettings(SchemeCodeStyleSettings.class);
69 | return !defineFormsTextArea.getText().equals(scmSettings.defineForms);
70 | }
71 |
72 | public JComponent getPanel()
73 | {
74 | return panel;
75 | }
76 |
77 | protected void resetImpl(CodeStyleSettings settings)
78 | {
79 | SchemeCodeStyleSettings scmSettings = settings.getCustomSettings(SchemeCodeStyleSettings.class);
80 | setSettings(scmSettings);
81 | updatePreview();
82 | }
83 |
84 | private void setSettings(SchemeCodeStyleSettings settings)
85 | {
86 | defineFormsTextArea.setText(settings.defineForms);
87 | //todo add more
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/schemely/scheme/common/ReaderThread.java:
--------------------------------------------------------------------------------
1 | package schemely.scheme.common;
2 |
3 | import org.apache.log4j.Logger;
4 |
5 | import java.io.IOException;
6 | import java.io.Reader;
7 | import java.util.concurrent.atomic.AtomicBoolean;
8 |
9 | /**
10 | * @author Colin Fleming
11 | */
12 | public abstract class ReaderThread implements Runnable
13 | {
14 | private static final Logger log = Logger.getLogger(ReaderThread.class);
15 |
16 | private final Reader myReader;
17 | private final AtomicBoolean terminated;
18 | private boolean skipLF = false;
19 |
20 | private final char[] myBuffer = new char[8192];
21 |
22 | public ReaderThread(Reader reader, AtomicBoolean terminated)
23 | {
24 | myReader = reader;
25 | this.terminated = terminated;
26 | }
27 |
28 | public void run()
29 | {
30 | try
31 | {
32 | while (true)
33 | {
34 | int rc = readAvailable();
35 | if (rc == DONE)
36 | {
37 | break;
38 | }
39 | Thread.sleep(rc == READ_SOME ? 1L : 50L);
40 | }
41 | }
42 | catch (InterruptedException ignore)
43 | {
44 | }
45 | catch (IOException e)
46 | {
47 | log.error("Error reading", e);
48 | }
49 | catch (Exception e)
50 | {
51 | log.error("Error reading", e);
52 | }
53 | }
54 |
55 | private static final int DONE = 0;
56 | private static final int READ_SOME = 1;
57 | private static final int READ_NONE = 2;
58 |
59 | private synchronized int readAvailable() throws IOException
60 | {
61 | char[] buffer = myBuffer;
62 | StringBuilder token = new StringBuilder();
63 | int rc = READ_NONE;
64 | while (myReader.ready())
65 | {
66 | int n = myReader.read(buffer);
67 | if (n <= 0)
68 | {
69 | break;
70 | }
71 | rc = READ_SOME;
72 |
73 | for (int i = 0; i < n; i++)
74 | {
75 | char c = buffer[i];
76 | if (skipLF && c != '\n')
77 | {
78 | token.append('\r');
79 | }
80 |
81 | if (c == '\r')
82 | {
83 | skipLF = true;
84 | }
85 | else
86 | {
87 | skipLF = false;
88 | token.append(c);
89 | }
90 |
91 | if (c == '\n')
92 | {
93 | textAvailable(token.toString());
94 | token.setLength(0);
95 | }
96 | }
97 | }
98 |
99 | if (token.length() != 0)
100 | {
101 | textAvailable(token.toString());
102 | token.setLength(0);
103 | }
104 |
105 | if (terminated.get())
106 | {
107 | try
108 | {
109 | myReader.close();
110 | }
111 | catch (IOException ignored)
112 | {
113 | }
114 |
115 | return DONE;
116 | }
117 |
118 | return rc;
119 | }
120 |
121 | protected abstract void textAvailable(String s);
122 | }
123 |
--------------------------------------------------------------------------------
/src/dk/brics/automaton/TransitionComparator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * dk.brics.automaton
3 | *
4 | * Copyright (c) 2001-2009 Anders Moeller
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without
8 | * modification, are permitted provided that the following conditions
9 | * are met:
10 | * 1. Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * 2. Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | * 3. The name of the author may not be used to endorse or promote products
16 | * derived from this software without specific prior written permission.
17 | *
18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 | */
29 |
30 | package dk.brics.automaton;
31 |
32 | import java.io.Serializable;
33 | import java.util.Comparator;
34 |
35 | class TransitionComparator implements Comparator, Serializable {
36 |
37 | static final long serialVersionUID = 10001;
38 |
39 | boolean to_first;
40 |
41 | TransitionComparator(boolean to_first) {
42 | this.to_first = to_first;
43 | }
44 |
45 | /**
46 | * Compares by (min, reverse max, to) or (to, min, reverse max).
47 | */
48 | public int compare(Transition t1, Transition t2) {
49 | if (to_first) {
50 | if (t1.to != t2.to) {
51 | if (t1.to == null)
52 | return -1;
53 | else if (t2.to == null)
54 | return 1;
55 | else if (t1.to.number < t2.to.number)
56 | return -1;
57 | else if (t1.to.number > t2.to.number)
58 | return 1;
59 | }
60 | }
61 | if (t1.min < t2.min)
62 | return -1;
63 | if (t1.min > t2.min)
64 | return 1;
65 | if (t1.max > t2.max)
66 | return -1;
67 | if (t1.max < t2.max)
68 | return 1;
69 | if (!to_first) {
70 | if (t1.to != t2.to) {
71 | if (t1.to == null)
72 | return -1;
73 | else if (t2.to == null)
74 | return 1;
75 | else if (t1.to.number < t2.to.number)
76 | return -1;
77 | else if (t1.to.number > t2.to.number)
78 | return 1;
79 | }
80 | }
81 | return 0;
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/dk/brics/automaton/StatePair.java:
--------------------------------------------------------------------------------
1 | /*
2 | * dk.brics.automaton
3 | *
4 | * Copyright (c) 2001-2009 Anders Moeller
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without
8 | * modification, are permitted provided that the following conditions
9 | * are met:
10 | * 1. Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * 2. Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | * 3. The name of the author may not be used to endorse or promote products
16 | * derived from this software without specific prior written permission.
17 | *
18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 | */
29 |
30 | package dk.brics.automaton;
31 |
32 | /**
33 | * Pair of states.
34 | * @author Anders Møller <amoeller@brics.dk >
35 | */
36 | public class StatePair {
37 | State s;
38 | State s1;
39 | State s2;
40 |
41 | StatePair(State s, State s1, State s2) {
42 | this.s = s;
43 | this.s1 = s1;
44 | this.s2 = s2;
45 | }
46 |
47 | /**
48 | * Constructs a new state pair.
49 | * @param s1 first state
50 | * @param s2 second state
51 | */
52 | public StatePair(State s1, State s2) {
53 | this.s1 = s1;
54 | this.s2 = s2;
55 | }
56 |
57 | /**
58 | * Returns first component of this pair.
59 | * @return first state
60 | */
61 | public State getFirstState() {
62 | return s1;
63 | }
64 |
65 | /**
66 | * Returns second component of this pair.
67 | * @return second state
68 | */
69 | public State getSecondState() {
70 | return s2;
71 | }
72 |
73 | /**
74 | * Checks for equality.
75 | * @param obj object to compare with
76 | * @return true if obj represents the same pair of states as this pair
77 | */
78 | @Override
79 | public boolean equals(Object obj) {
80 | if (obj instanceof StatePair) {
81 | StatePair p = (StatePair)obj;
82 | return p.s1 == s1 && p.s2 == s2;
83 | }
84 | else
85 | return false;
86 | }
87 |
88 | /**
89 | * Returns hash code.
90 | * @return hash code
91 | */
92 | @Override
93 | public int hashCode() {
94 | return s1.hashCode() + s2.hashCode();
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/dk/brics/automaton/DatatypesAutomatonProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * dk.brics.automaton
3 | *
4 | * Copyright (c) 2001-2009 Anders Moeller
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without
8 | * modification, are permitted provided that the following conditions
9 | * are met:
10 | * 1. Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * 2. Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | * 3. The name of the author may not be used to endorse or promote products
16 | * derived from this software without specific prior written permission.
17 | *
18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 | */
29 |
30 | package dk.brics.automaton;
31 |
32 | /**
33 | * Automaton provider based on {@link Datatypes}.
34 | */
35 | public class DatatypesAutomatonProvider implements AutomatonProvider {
36 |
37 | private boolean enable_unicodeblocks, enable_unicodecategories, enable_xml;
38 |
39 | /**
40 | * Constructs a new automaton provider that recognizes all names
41 | * from {@link Datatypes#get(String)}.
42 | */
43 | public DatatypesAutomatonProvider() {
44 | enable_unicodeblocks = enable_unicodecategories = enable_xml = true;
45 | }
46 |
47 | /**
48 | * Constructs a new automaton provider that recognizes some of the names
49 | * from {@link Datatypes#get(String)}
50 | * @param enable_unicodeblocks if true, enable Unicode block names
51 | * @param enable_unicodecategories if true, enable Unicode category names
52 | * @param enable_xml if true, enable XML related names
53 | */
54 | public DatatypesAutomatonProvider(boolean enable_unicodeblocks, boolean enable_unicodecategories, boolean enable_xml) {
55 | this.enable_unicodeblocks = enable_unicodeblocks;
56 | this.enable_unicodecategories = enable_unicodecategories;
57 | this.enable_xml = enable_xml;
58 | }
59 |
60 | public Automaton getAutomaton(String name) {
61 | if ((enable_unicodeblocks && Datatypes.isUnicodeBlockName(name))
62 | || (enable_unicodecategories && Datatypes.isUnicodeCategoryName(name))
63 | || (enable_xml && Datatypes.isXMLName(name)))
64 | return Datatypes.get(name);
65 | return null;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/schemely/compiler/SchemeCompilerConfigurable.java:
--------------------------------------------------------------------------------
1 | package schemely.compiler;
2 |
3 | import com.intellij.openapi.options.Configurable;
4 | import com.intellij.openapi.options.ConfigurationException;
5 | import com.intellij.openapi.project.Project;
6 | import org.jetbrains.annotations.Nls;
7 |
8 | import javax.swing.Icon;
9 | import javax.swing.JCheckBox;
10 | import javax.swing.JComponent;
11 | import javax.swing.JPanel;
12 | import javax.swing.JTextField;
13 |
14 | public class SchemeCompilerConfigurable implements Configurable
15 | {
16 | private JCheckBox modulesDefaultToStaticCheckBox;
17 | private JCheckBox warnOnUnknownMembersCheckBox;
18 | private JCheckBox warnInvokeUnknownMethodCheckBox;
19 | private JCheckBox warnOnUndefinedVariablesCheckBox;
20 | private JTextField classNamePrefixField;
21 | private JPanel panel;
22 | private JCheckBox treatWarningsAsErrorsCheckBox;
23 |
24 | private SchemeCompilerSettings settings;
25 |
26 | public SchemeCompilerConfigurable(SchemeCompilerSettings settings)
27 | {
28 | this.settings = settings;
29 | }
30 |
31 | @Nls
32 | public String getDisplayName()
33 | {
34 | return "Scheme Compiler";
35 | }
36 |
37 | public Icon getIcon()
38 | {
39 | return null;
40 | }
41 |
42 | public String getHelpTopic()
43 | {
44 | return null;
45 | }
46 |
47 | public JComponent createComponent()
48 | {
49 | return panel;
50 | }
51 |
52 | public boolean isModified()
53 | {
54 | return !settings.prefix.equals(classNamePrefixField.getText()) ||
55 | (settings.modulesDefaultToStatic != modulesDefaultToStaticCheckBox.isSelected()) ||
56 | (settings.warnUnknownMember != warnOnUnknownMembersCheckBox.isSelected()) ||
57 | (settings.warnInvokeUnknownMethod != warnInvokeUnknownMethodCheckBox.isSelected()) ||
58 | (settings.warnUndefinedVariable != warnOnUndefinedVariablesCheckBox.isSelected()) ||
59 | (settings.warningsAsErrors != treatWarningsAsErrorsCheckBox.isSelected());
60 | }
61 |
62 | public void apply() throws ConfigurationException
63 | {
64 | settings.prefix = classNamePrefixField.getText();
65 | settings.modulesDefaultToStatic = modulesDefaultToStaticCheckBox.isSelected();
66 | settings.warnUnknownMember = warnOnUnknownMembersCheckBox.isSelected();
67 | settings.warnInvokeUnknownMethod = warnInvokeUnknownMethodCheckBox.isSelected();
68 | settings.warnUndefinedVariable = warnOnUndefinedVariablesCheckBox.isSelected();
69 | settings.warningsAsErrors = treatWarningsAsErrorsCheckBox.isSelected();
70 | }
71 |
72 | public void reset()
73 | {
74 | classNamePrefixField.setText(settings.prefix);
75 | modulesDefaultToStaticCheckBox.setSelected(settings.modulesDefaultToStatic);
76 | warnOnUnknownMembersCheckBox.setSelected(settings.warnUnknownMember);
77 | warnInvokeUnknownMethodCheckBox.setSelected(settings.warnInvokeUnknownMethod);
78 | warnOnUndefinedVariablesCheckBox.setSelected(settings.warnUndefinedVariable);
79 | treatWarningsAsErrorsCheckBox.setSelected(settings.warningsAsErrors);
80 | }
81 |
82 | public void disposeUIResources()
83 | {
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/schemely/compiler/SchemeOutputParser.java:
--------------------------------------------------------------------------------
1 | package schemely.compiler;
2 |
3 | import com.intellij.compiler.OutputParser;
4 | import com.intellij.openapi.compiler.CompilerMessageCategory;
5 | import com.intellij.openapi.vfs.LocalFileSystem;
6 | import com.intellij.openapi.vfs.VirtualFileManager;
7 | import org.apache.log4j.Logger;
8 |
9 | /**
10 | * @author Colin Fleming
11 | */
12 | public class SchemeOutputParser extends OutputParser
13 | {
14 | private static final Logger log = Logger.getLogger(SchemeOutputParser.class);
15 | private static final String COMPILING_PREFIX = "(compiling ";
16 | private static final String WARNING_SUBSTRING = ": warning";
17 |
18 | private String errorPrefix = null;
19 | private String fileURL = null;
20 |
21 | @Override
22 | public boolean processMessageLine(Callback callback)
23 | {
24 | if (super.processMessageLine(callback)) {
25 | return true;
26 | }
27 | String line = callback.getCurrentLine();
28 | if (line == null) {
29 | return false;
30 | }
31 |
32 | if (line.startsWith(COMPILING_PREFIX))
33 | {
34 | int index = line.indexOf(" to ");
35 | if (index == -1)
36 | {
37 | index = line.indexOf(')');
38 | }
39 | if (index > 0)
40 | {
41 | String filename = line.substring(COMPILING_PREFIX.length(), index);
42 | errorPrefix = filename + ":";
43 | fileURL = VirtualFileManager.constructUrl(LocalFileSystem.PROTOCOL, filename);
44 | }
45 |
46 | if (line.endsWith(")"))
47 | {
48 | callback.setProgressText(line.substring(1, line.length() -1));
49 | }
50 | else
51 | {
52 | callback.setProgressText(line.substring(1));
53 | }
54 | }
55 | else if ((errorPrefix != null) && line.startsWith(errorPrefix))
56 | {
57 | int offset = errorPrefix.length();
58 | if (Character.isDigit(line.charAt(offset)))
59 | {
60 | int lineNum = 0;
61 | while (Character.isDigit(line.charAt(offset)))
62 | {
63 | lineNum = lineNum * 10 + (line.charAt(offset) - '0');
64 | offset++;
65 | }
66 | if (line.charAt(offset) == ':')
67 | {
68 | offset++;
69 | if (Character.isDigit(line.charAt(offset)))
70 | {
71 | int character = 0;
72 | while (Character.isDigit(line.charAt(offset)))
73 | {
74 | character = character * 10 + (line.charAt(offset) - '0');
75 | offset++;
76 | }
77 |
78 | callback.message(CompilerMessageCategory.ERROR, line, fileURL, lineNum, character);
79 | return true;
80 | }
81 | }
82 |
83 | callback.message(CompilerMessageCategory.ERROR, line, fileURL, lineNum, -1);
84 | return true;
85 | }
86 |
87 | callback.message(CompilerMessageCategory.ERROR, line, fileURL, -1, -1);
88 | }
89 | else if (line.contains(WARNING_SUBSTRING))
90 | {
91 | callback.message(CompilerMessageCategory.WARNING, line, null, -1, -1);
92 | }
93 | else
94 | {
95 | callback.message(CompilerMessageCategory.WARNING, line, null, -1, -1);
96 | }
97 |
98 | return true;
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/schemely/scheme/sisc/psi/SISCList.java:
--------------------------------------------------------------------------------
1 | package schemely.scheme.sisc.psi;
2 |
3 | import com.intellij.lang.ASTNode;
4 | import com.intellij.psi.PsiElement;
5 | import com.intellij.psi.PsiNamedElement;
6 | import com.intellij.psi.ResolveState;
7 | import com.intellij.psi.scope.PsiScopeProcessor;
8 | import com.intellij.psi.util.PsiTreeUtil;
9 | import org.jetbrains.annotations.NotNull;
10 | import schemely.psi.impl.list.SchemeList;
11 | import schemely.psi.impl.symbols.SchemeIdentifier;
12 | import schemely.psi.resolve.ResolveUtil;
13 |
14 | /**
15 | * @author Colin Fleming
16 | */
17 | public class SISCList extends SchemeList
18 | {
19 | public static final String MODULE = "module";
20 |
21 | public SISCList(@NotNull ASTNode astNode)
22 | {
23 | super(astNode);
24 | }
25 |
26 | @Override
27 | public boolean processDeclarations(@NotNull PsiScopeProcessor processor,
28 | @NotNull ResolveState state,
29 | PsiElement lastParent,
30 | @NotNull PsiElement place)
31 | {
32 | if (isModule())
33 | {
34 | return processModuleDeclaration(processor, this, place);
35 | }
36 |
37 | return super.processDeclarations(processor, state, lastParent, place);
38 | }
39 |
40 | private static boolean processModuleDeclaration(PsiScopeProcessor scopeProcessor, SchemeList module, PsiElement place)
41 | {
42 | PsiElement symbolsOrName = module.getSecondNonLeafElement();
43 | SchemeIdentifier name = null;
44 | SchemeList symbols = null;
45 |
46 | // (module name (symbols)) or (module (symbols))
47 | if (symbolsOrName instanceof SchemeIdentifier)
48 | {
49 | name = (SchemeIdentifier) symbolsOrName;
50 | symbolsOrName = ResolveUtil.getNextNonLeafElement(symbolsOrName);
51 | }
52 | if (symbolsOrName instanceof SchemeList)
53 | {
54 | symbols = (SchemeList) symbolsOrName;
55 | }
56 |
57 | // Module name & symbols resolve to the symbol itself
58 | if ((PsiTreeUtil.isAncestor(name, place, false) || PsiTreeUtil.isAncestor(symbols, place, false)))
59 | {
60 | if (!ResolveUtil.processElement(scopeProcessor, (PsiNamedElement) place))
61 | {
62 | return false;
63 | }
64 | }
65 |
66 | // Otherwise symbols are only visible outside the module
67 | if (!PsiTreeUtil.isAncestor(module, place, false))
68 | {
69 | if (name != null)
70 | {
71 | if (!ResolveUtil.processElement(scopeProcessor, name))
72 | {
73 | return false;
74 | }
75 | }
76 | if (symbols != null)
77 | {
78 | for (SchemeIdentifier identifier : symbols.getAllIdentifiers())
79 | {
80 | if (!ResolveUtil.processElement(scopeProcessor, identifier))
81 | {
82 | return false;
83 | }
84 | }
85 | }
86 | }
87 |
88 | // TODO internal defines
89 |
90 | return true;
91 | }
92 |
93 | public boolean isModule()
94 | {
95 | String headText = getHeadText();
96 | return MODULE.equals(headText);
97 | }
98 |
99 | @Override
100 | public boolean isTopLevelDefinition()
101 | {
102 | return isModule() || super.isTopLevelDefinition();
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/test/schemely/formatter/FormatterTest.java:
--------------------------------------------------------------------------------
1 | package schemely.formatter;
2 |
3 | import com.intellij.openapi.application.ApplicationManager;
4 | import com.intellij.openapi.application.PathManager;
5 | import com.intellij.openapi.util.io.FileUtil;
6 | import com.intellij.openapi.util.text.StringUtil;
7 | import com.intellij.psi.PsiDocumentManager;
8 | import com.intellij.psi.codeStyle.CodeStyleManager;
9 | import com.intellij.testFramework.LightCodeInsightTestCase;
10 |
11 | import java.io.File;
12 | import java.io.IOException;
13 |
14 | /**
15 | * @author Colin Fleming
16 | */
17 | public class FormatterTest extends LightCodeInsightTestCase
18 | {
19 | public void testIndentQuoted() throws IOException
20 | {
21 | doTest();
22 | }
23 |
24 | public void testInlineComment() throws IOException
25 | {
26 | doTest();
27 | }
28 |
29 | public void testInlineComment2() throws IOException
30 | {
31 | doTest();
32 | }
33 |
34 | public void testIssue18() throws IOException
35 | {
36 | doTest();
37 | }
38 |
39 | public void testListOfLists() throws IOException
40 | {
41 | doTest();
42 | }
43 |
44 | public void doTest() throws IOException
45 | {
46 | // TODO: Currently requires idea.home.path to be set to the project root
47 | String homePath = PathManager.getHomePath();
48 | String testDataPath = homePath + "/testData/formatter";
49 |
50 | String testName = getTestName();
51 | String source = doLoadFile(testDataPath, testName + ".scm");
52 | String result = doLoadFile(testDataPath, testName + ".result.scm");
53 |
54 | configureFromFileText("formatting.scm", source);
55 |
56 | CodeStyleManager manager = CodeStyleManager.getInstance(ourProject);
57 | manager.reformatText(myFile, 0, myFile.getTextLength());
58 |
59 | ApplicationManager.getApplication().runWriteAction(new Runnable()
60 | {
61 | @Override
62 | public void run()
63 | {
64 | PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
65 | }
66 | });
67 |
68 | String formatted = myFile.getText();
69 | assertEquals(result, formatted);
70 | }
71 |
72 | private String getTestName()
73 | {
74 | String name = getName();
75 | assertTrue("Test name should start with 'test': " + name, name.startsWith("test"));
76 | name = name.substring("test".length());
77 | StringBuilder builder = new StringBuilder();
78 | boolean lastLowerCase = false;
79 | int i = 0;
80 | while (i < name.length())
81 | {
82 | char ch = name.charAt(i);
83 | if (Character.isUpperCase(ch))
84 | {
85 | if (lastLowerCase)
86 | {
87 | builder.append("-");
88 | }
89 | builder.append(Character.toLowerCase(ch));
90 | }
91 | else
92 | {
93 | builder.append(ch);
94 | lastLowerCase = true;
95 | }
96 | i++;
97 | }
98 | return builder.toString();
99 | }
100 |
101 | private static String doLoadFile(String myFullDataPath, String name) throws IOException
102 | {
103 | String fullName = myFullDataPath + File.separatorChar + name;
104 | String text = new String(FileUtil.loadFileText(new File(fullName))).trim();
105 | text = StringUtil.convertLineSeparators(text);
106 | return text;
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/schemely/scheme/sisc/lexer/SISCLexer.java:
--------------------------------------------------------------------------------
1 | package schemely.scheme.sisc.lexer;
2 |
3 | import schemely.lexer.SchemeLexer;
4 | import schemely.lexer.Tokens;
5 |
6 | /**
7 | * @author Colin Fleming
8 | */
9 | public class SISCLexer extends SchemeLexer
10 | {
11 | @Override
12 | protected boolean implementationSpecific()
13 | {
14 | if (peek() == '#')
15 | {
16 | if (peek(1) == '%')
17 | {
18 | // TODO - what do these mean?
19 | cursor += 2;
20 | if (isIdentifierInitial(peek()))
21 | {
22 | cursor++;
23 | while (isIdentifierSubsequent(peek()))
24 | {
25 | cursor++;
26 | }
27 | type = Tokens.IDENTIFIER;
28 | }
29 | else
30 | {
31 | bad();
32 | }
33 | return true;
34 | }
35 | else if (Character.isDigit(peek(1)))
36 | {
37 | cursor += 2;
38 | while (Character.isDigit(peek()))
39 | {
40 | cursor++;
41 | }
42 | if (peek() == '=')
43 | {
44 | cursor++;
45 | type = SISCTokens.PTR_DEF;
46 | }
47 | else if (peek() == '#')
48 | {
49 | cursor++;
50 | type = SISCTokens.PTR_REF;
51 | }
52 | else if (peek() == '(')
53 | {
54 | cursor++;
55 | type = Tokens.OPEN_VECTOR;
56 | }
57 | else
58 | {
59 | bad();
60 | }
61 | return true;
62 | }
63 | else if (peek(1) == '\'')
64 | {
65 | cursor += 2;
66 | type = SISCTokens.SYNTAX_QUOTE;
67 | return true;
68 | }
69 | }
70 | else if ((peek() == '.') && isIdentifierInitial(peek(1)))
71 | {
72 | // TODO - find out what the story is here - does SISC allow any symbol to start with '.'?
73 | cursor++;
74 | readIdentifier();
75 | return true;
76 | }
77 | else if (peek() == '|')
78 | {
79 | cursor++;
80 | if (isIdentifierInitial(peek()))
81 | {
82 | cursor++;
83 | while (isIdentifierSubsequent(peek()))
84 | {
85 | cursor++;
86 | }
87 | if (peek() == '|')
88 | {
89 | cursor++;
90 | type = Tokens.IDENTIFIER;
91 | }
92 | else
93 | {
94 | bad();
95 | }
96 | }
97 | else
98 | {
99 | bad();
100 | }
101 | return true;
102 | }
103 | else if (has(3) && lookingAt("->") && isIdentifierInitial(peek(2)))
104 | {
105 | cursor += 2;
106 | readIdentifier();
107 | return true;
108 | }
109 |
110 | return test("#!eof", Tokens.SPECIAL) ||
111 | test("#!+inf", Tokens.SPECIAL) ||
112 | test("#!-inf", Tokens.SPECIAL) ||
113 | test("#!nan", Tokens.SPECIAL) ||
114 | test("#!void", Tokens.SPECIAL) ||
115 | test("#\\backspace", Tokens.CHAR_LITERAL) ||
116 | test("#\\nul", Tokens.CHAR_LITERAL) ||
117 | test("#\\page", Tokens.CHAR_LITERAL) ||
118 | test("#\\return", Tokens.CHAR_LITERAL) ||
119 | test("#\\rubout", Tokens.CHAR_LITERAL) ||
120 | test("#\\tab", Tokens.CHAR_LITERAL);
121 |
122 | // TODO unicode char literals
123 | // TODO boxes
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/src/schemely/formatter/codeStyle/SchemeCodeStylePanel.form:
--------------------------------------------------------------------------------
1 |
2 |
66 |
--------------------------------------------------------------------------------
/src/schemely/conversion/JavaToSchemeAction.java:
--------------------------------------------------------------------------------
1 | package schemely.conversion;
2 |
3 | import com.intellij.openapi.actionSystem.*;
4 | import com.intellij.openapi.application.ApplicationManager;
5 | import com.intellij.openapi.editor.Document;
6 | import com.intellij.psi.PsiDirectory;
7 | import com.intellij.psi.PsiDocumentManager;
8 | import com.intellij.psi.PsiFile;
9 | import com.intellij.psi.PsiJavaFile;
10 | import com.intellij.psi.codeStyle.CodeStyleManager;
11 | import com.intellij.psi.codeStyle.CodeStyleSettings;
12 | import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
13 |
14 | class JavaToSchemeAction extends AnAction
15 | {
16 | @Override
17 | public void update(AnActionEvent e)
18 | {
19 | Presentation presentation = e.getPresentation();
20 |
21 | try
22 | {
23 | DataContext dataContext = e.getDataContext();
24 | Object data = dataContext.getData(DataConstants.PSI_FILE);
25 | if (data instanceof PsiJavaFile)
26 | {
27 | PsiJavaFile file = (PsiJavaFile) data;
28 | PsiDirectory directory = file.getContainingDirectory();
29 | if ((directory != null) && directory.isWritable())
30 | {
31 | presentation.setEnabled(true);
32 | presentation.setVisible(true);
33 | }
34 | }
35 | else
36 | {
37 | presentation.setEnabled(false);
38 | presentation.setVisible(false);
39 | }
40 | }
41 | catch (Exception ignore)
42 | {
43 | presentation.setEnabled(false);
44 | presentation.setVisible(false);
45 | }
46 | }
47 |
48 | @Override
49 | public void actionPerformed(AnActionEvent e)
50 | {
51 | Object data = e.getDataContext().getData(DataConstants.PSI_FILE);
52 | if (data instanceof PsiJavaFile)
53 | {
54 | final PsiJavaFile file = (PsiJavaFile) data;
55 |
56 | ApplicationManager.getApplication().runWriteAction(new Runnable()
57 | {
58 | @Override
59 | public void run()
60 | {
61 | PsiDirectory directory = file.getContainingDirectory();
62 | String name = file.getName().substring(0, file.getName().length() - 5);
63 |
64 | PsiFile newFile = directory.createFile(name + ".scm");
65 | JavaToScheme toScheme = new JavaToScheme();
66 | String newText = toScheme.convertPsiToText(file).trim();
67 | Document document = PsiDocumentManager.getInstance(newFile.getProject()).getDocument(newFile);
68 | document.insertString(0, newText);
69 | PsiDocumentManager.getInstance(newFile.getProject()).commitDocument(document);
70 | CodeStyleManager manager = CodeStyleManager.getInstance(newFile.getProject());
71 | CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(newFile.getProject());
72 | int keep_blank_lines_in_code = settings.KEEP_BLANK_LINES_IN_CODE;
73 | int keep_blank_lines_in_declarations = settings.KEEP_BLANK_LINES_IN_DECLARATIONS;
74 | int keep_blank_lines_before_rbrace = settings.KEEP_BLANK_LINES_BEFORE_RBRACE;
75 | settings.KEEP_BLANK_LINES_IN_CODE = 0;
76 | settings.KEEP_BLANK_LINES_IN_DECLARATIONS = 0;
77 | settings.KEEP_BLANK_LINES_BEFORE_RBRACE = 0;
78 | manager.reformatText(newFile, 0, newFile.getTextLength());
79 | settings.KEEP_BLANK_LINES_IN_CODE = keep_blank_lines_in_code;
80 | settings.KEEP_BLANK_LINES_IN_DECLARATIONS = keep_blank_lines_in_declarations;
81 | settings.KEEP_BLANK_LINES_BEFORE_RBRACE = keep_blank_lines_before_rbrace;
82 | newFile.navigate(true);
83 | }
84 | });
85 | }
86 | }
87 | }
--------------------------------------------------------------------------------