├── testData └── formatter │ ├── list-of-lists.scm │ ├── indent-quoted.scm │ ├── list-of-lists.result.scm │ ├── indent-quoted.result.scm │ ├── inline-comment2.scm │ ├── issue18.scm │ ├── inline-comment2.result.scm │ ├── issue18.result.scm │ ├── inline-comment.scm │ └── inline-comment.result.scm ├── lib ├── kawa-1.11.jar ├── sisc-1.16.6.jar ├── sisc-lib-1.16.6.jar ├── sisc-opt-1.16.6.jar ├── sisc-src-1.16.6.jar └── miglayout-3.7.4-swing.jar ├── tag-jar.sh ├── resources ├── fileTemplates │ └── j2ee │ │ ├── SchemeFile.clj.ft │ │ └── SchemeFile.clj.html └── schemely │ └── icons │ ├── lambda.png │ ├── method.png │ ├── symbol.png │ ├── function.png │ ├── java_field.png │ ├── java_method.png │ └── namespace.png ├── .gitignore ├── scheme.properties ├── .idea ├── copyright │ └── profiles_settings.xml ├── ant.xml ├── encodings.xml ├── vcs.xml ├── dictionaries │ └── colin.xml ├── inspectionProfiles │ ├── profiles_settings.xml │ └── Project_Default.xml ├── modules.xml ├── compiler.xml ├── projectCodeStyle.xml └── misc.xml ├── src ├── schemely │ ├── repl │ │ ├── actions │ │ │ ├── SchemeReplActionGroup.java │ │ │ ├── RunTopSExprAction.java │ │ │ ├── RunLastSExprAction.java │ │ │ ├── RunSelectedTextAction.java │ │ │ └── LoadSchemeFileInConsoleAction.java │ │ ├── REPLProvider.java │ │ ├── SchemeConsoleView.java │ │ ├── UnsupportedREPLProvider.java │ │ ├── toolwindow │ │ │ ├── REPLToolWindowFactory.java │ │ │ └── actions │ │ │ │ ├── REPLEnterAction.java │ │ │ │ ├── ExecuteImmediatelyAction.java │ │ │ │ ├── NewExternalConsoleAction.java │ │ │ │ ├── NewInProcessConsoleAction.java │ │ │ │ ├── HistoryNextAction.java │ │ │ │ └── HistoryPreviousAction.java │ │ ├── SchemeConsoleElement.java │ │ ├── LanguageConsoleViewImpl.java │ │ └── ConsoleHistoryModel.java │ ├── psi │ │ ├── api │ │ │ ├── SchemePsiElement.java │ │ │ └── SchemeBraced.java │ │ ├── impl │ │ │ ├── SchemeLiteral.java │ │ │ ├── SchemeQuoted.java │ │ │ ├── symbols │ │ │ │ ├── SymbolUtils.java │ │ │ │ └── CompleteSymbol.java │ │ │ ├── search │ │ │ │ └── SchemeSourceFilterScope.java │ │ │ ├── SchemeVector.java │ │ │ ├── SchemePsiElementBase.java │ │ │ └── list │ │ │ │ └── SchemeListBase.java │ │ ├── stubs │ │ │ ├── api │ │ │ │ └── SchemeFileStub.java │ │ │ ├── index │ │ │ │ ├── SchemeClassNameIndex.java │ │ │ │ └── SchemeFullScriptNameIndex.java │ │ │ ├── SchemeFileStubBuilder.java │ │ │ ├── impl │ │ │ │ └── SchemeFileStubImpl.java │ │ │ └── elements │ │ │ │ └── SchemeStubFileElementType.java │ │ ├── resolve │ │ │ ├── SchemeResolveResult.java │ │ │ ├── completion │ │ │ │ └── CompletionProcessor.java │ │ │ ├── processors │ │ │ │ ├── ResolveProcessor.java │ │ │ │ └── SymbolResolveProcessor.java │ │ │ └── ResolveUtil.java │ │ └── util │ │ │ ├── SchemeTextUtil.java │ │ │ ├── SchemePsiElementFactory.java │ │ │ └── SchemePsiElementFactoryImpl.java │ ├── SchemeLanguage.java │ ├── lexer │ │ ├── TokenSets.java │ │ └── Tokens.java │ ├── scheme │ │ ├── sisc │ │ │ ├── psi │ │ │ │ ├── SISCPointerDef.java │ │ │ │ ├── SISCPointerRef.java │ │ │ │ ├── SISCPsiCreator.java │ │ │ │ └── SISCList.java │ │ │ ├── parser │ │ │ │ ├── SISCAST.java │ │ │ │ └── SISCParser.java │ │ │ ├── lexer │ │ │ │ ├── SISCTokens.java │ │ │ │ └── SISCLexer.java │ │ │ ├── SISCConfigUtil.java │ │ │ └── SISCScheme.java │ │ ├── REPLException.java │ │ ├── kawa │ │ │ ├── impl │ │ │ │ └── KawaREPLMain.java │ │ │ └── KawaScheme.java │ │ ├── Scheme.java │ │ ├── SchemeImplementation.java │ │ ├── REPL.java │ │ └── common │ │ │ ├── REPLUtil.java │ │ │ └── ReaderThread.java │ ├── parser │ │ ├── SchemePsiCreator.java │ │ ├── SchemeElementType.java │ │ ├── AST.java │ │ └── DefaultPsiCreator.java │ ├── highlighter │ │ ├── SchemeEditorHighlighter.java │ │ ├── SchemeBraceMatcher.java │ │ └── SchemeCommenter.java │ ├── file │ │ ├── SchemeFileTypeLoader.java │ │ └── SchemeFileType.java │ ├── compiler │ │ ├── SchemeCompilerSettingsFactory.java │ │ ├── CompilerProjectComponent.java │ │ ├── SchemeCompilerSettings.java │ │ ├── SchemeCompilerConfigurable.java │ │ └── SchemeOutputParser.java │ ├── formatter │ │ ├── codeStyle │ │ │ ├── SchemeCodeStyleSettings.java │ │ │ ├── SchemeCodeStyleSettingsProvider.java │ │ │ ├── SchemeFormatConfigurable.java │ │ │ ├── SchemeCodeStylePanel.java │ │ │ └── SchemeCodeStylePanel.form │ │ ├── SchemeFormattingModelBuilder.java │ │ ├── processors │ │ │ └── SchemeSpacingProcessor.java │ │ ├── ListBlock.java │ │ └── SchemeIndentOptionsProvider.java │ ├── utils │ │ ├── SchemeUtils.java │ │ ├── Editors.java │ │ ├── SchemeNamesUtil.java │ │ ├── Actions.java │ │ ├── SchemeNamesValidator.java │ │ ├── LibrariesUtil.java │ │ └── SchemeConfigUtil.java │ ├── SchemeIcons.java │ ├── structure │ │ ├── SchemeStructureViewBuilderFactory.java │ │ └── SchemeStructureViewModel.java │ ├── SchemeBundle.java │ ├── editor │ │ ├── selection │ │ │ ├── SchemeLiteralSelectioner.java │ │ │ ├── SchemeIdentifierSelectioner.java │ │ │ └── SchemeListSelectioner.java │ │ └── SchemeQuoteHandler.java │ ├── navigation │ │ └── SchemeNavigationOffsetProvider.java │ ├── gotoclass │ │ └── SchemeGoToSymbolContributor.java │ ├── settings │ │ └── SchemeProjectSettings.java │ ├── completion │ │ └── SchemeCompletionContributor.java │ ├── findUsages │ │ └── SchemeFindUsagesProvider.java │ ├── actions │ │ ├── NewSchemeFileAction.java │ │ └── SchemeTemplatesFactory.java │ ├── SchemeFoldingBuilder.java │ └── conversion │ │ └── JavaToSchemeAction.java └── dk │ └── brics │ └── automaton │ ├── package.html │ ├── AutomatonProvider.java │ ├── TransitionComparator.java │ ├── StatePair.java │ └── DatatypesAutomatonProvider.java ├── test └── schemely │ ├── TestUtil.java │ ├── lexer │ ├── SISCLexerTest.java │ └── LexerTestBase.java │ ├── parser │ ├── ParserTest.java │ ├── SISCParserTest.java │ └── ParseTestCaseBase.java │ ├── scheme │ └── sisc │ │ ├── SISCOutputProcessorTest.java │ │ └── StreamTest.java │ ├── completion │ └── SchemeIdentifierMatcherTest.java │ └── formatter │ └── FormatterTest.java ├── todo.txt ├── scheme-src ├── conversion.scm └── test.scm ├── readme.markdown └── schemely.iml /testData/formatter/list-of-lists.scm: -------------------------------------------------------------------------------- 1 | ((a) 2 | (b)) 3 | -------------------------------------------------------------------------------- /testData/formatter/indent-quoted.scm: -------------------------------------------------------------------------------- 1 | (define a 2 | '(test)) 3 | -------------------------------------------------------------------------------- /testData/formatter/list-of-lists.result.scm: -------------------------------------------------------------------------------- 1 | ((a) 2 | (b)) 3 | -------------------------------------------------------------------------------- /testData/formatter/indent-quoted.result.scm: -------------------------------------------------------------------------------- 1 | (define a 2 | '(test)) 3 | -------------------------------------------------------------------------------- /testData/formatter/inline-comment2.scm: -------------------------------------------------------------------------------- 1 | (lambda (n) ;dispatch 2 | (+ 2 n)) 3 | -------------------------------------------------------------------------------- /testData/formatter/issue18.scm: -------------------------------------------------------------------------------- 1 | (define nth-elt 2 | (lambda (lst n) 3 | )) 4 | -------------------------------------------------------------------------------- /lib/kawa-1.11.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmf/schemely/HEAD/lib/kawa-1.11.jar -------------------------------------------------------------------------------- /lib/sisc-1.16.6.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmf/schemely/HEAD/lib/sisc-1.16.6.jar -------------------------------------------------------------------------------- /testData/formatter/inline-comment2.result.scm: -------------------------------------------------------------------------------- 1 | (lambda (n) ;dispatch 2 | (+ 2 n)) 3 | -------------------------------------------------------------------------------- /testData/formatter/issue18.result.scm: -------------------------------------------------------------------------------- 1 | (define nth-elt 2 | (lambda (lst n) 3 | )) 4 | -------------------------------------------------------------------------------- /lib/sisc-lib-1.16.6.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmf/schemely/HEAD/lib/sisc-lib-1.16.6.jar -------------------------------------------------------------------------------- /lib/sisc-opt-1.16.6.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmf/schemely/HEAD/lib/sisc-opt-1.16.6.jar -------------------------------------------------------------------------------- /lib/sisc-src-1.16.6.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmf/schemely/HEAD/lib/sisc-src-1.16.6.jar -------------------------------------------------------------------------------- /tag-jar.sh: -------------------------------------------------------------------------------- 1 | git rev-parse HEAD > /tmp/git-version 2 | zip -uj schemely.zip /tmp/git-version 3 | -------------------------------------------------------------------------------- /lib/miglayout-3.7.4-swing.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmf/schemely/HEAD/lib/miglayout-3.7.4-swing.jar -------------------------------------------------------------------------------- /resources/fileTemplates/j2ee/SchemeFile.clj.ft: -------------------------------------------------------------------------------- 1 | #if ($PACKAGE_NAME != "")(ns ${PACKAGE_NAME}.${NAME}) 2 | #end -------------------------------------------------------------------------------- /resources/schemely/icons/lambda.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmf/schemely/HEAD/resources/schemely/icons/lambda.png -------------------------------------------------------------------------------- /resources/schemely/icons/method.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmf/schemely/HEAD/resources/schemely/icons/method.png -------------------------------------------------------------------------------- /resources/schemely/icons/symbol.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmf/schemely/HEAD/resources/schemely/icons/symbol.png -------------------------------------------------------------------------------- /resources/schemely/icons/function.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmf/schemely/HEAD/resources/schemely/icons/function.png -------------------------------------------------------------------------------- /resources/schemely/icons/java_field.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmf/schemely/HEAD/resources/schemely/icons/java_field.png -------------------------------------------------------------------------------- /resources/schemely/icons/java_method.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmf/schemely/HEAD/resources/schemely/icons/java_method.png -------------------------------------------------------------------------------- /resources/schemely/icons/namespace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmf/schemely/HEAD/resources/schemely/icons/namespace.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/workspace.xml 2 | out 3 | test-output 4 | jflex.log 5 | schemely.zip 6 | src/schemely/conversion/JavaToScala.scala 7 | 8 | -------------------------------------------------------------------------------- /testData/formatter/inline-comment.scm: -------------------------------------------------------------------------------- 1 | (define x 2 | ; A symbol 3 | 10) 4 | 5 | (define x 6 | ; A symbol 7 | ; Another line 8 | 10) 9 | -------------------------------------------------------------------------------- /testData/formatter/inline-comment.result.scm: -------------------------------------------------------------------------------- 1 | (define x 2 | ; A symbol 3 | 10) 4 | 5 | (define x 6 | ; A symbol 7 | ; Another line 8 | 10) 9 | -------------------------------------------------------------------------------- /scheme.properties: -------------------------------------------------------------------------------- 1 | idea.home=/Applications/IntelliJ IDEA 8.1.3.app/ 2 | java.home=/System/Library/Frameworks/JavaVM.framework/Home 3 | scheme.plugin.version=0.1 -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.idea/ant.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/dictionaries/colin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | browsable 5 | schemely 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/schemely/repl/actions/SchemeReplActionGroup.java: -------------------------------------------------------------------------------- 1 | package schemely.repl.actions; 2 | 3 | import com.intellij.openapi.actionSystem.DefaultActionGroup; 4 | 5 | public class SchemeReplActionGroup extends DefaultActionGroup 6 | { 7 | } 8 | -------------------------------------------------------------------------------- /src/schemely/psi/api/SchemePsiElement.java: -------------------------------------------------------------------------------- 1 | package schemely.psi.api; 2 | 3 | import com.intellij.psi.PsiElement; 4 | 5 | /** 6 | * @author Colin Fleming 7 | */ 8 | public interface SchemePsiElement extends PsiElement 9 | { 10 | 11 | int getQuotingLevel(); 12 | } 13 | -------------------------------------------------------------------------------- /src/schemely/SchemeLanguage.java: -------------------------------------------------------------------------------- 1 | package schemely; 2 | 3 | import com.intellij.lang.Language; 4 | 5 | public class SchemeLanguage extends Language 6 | { 7 | private static final String ID = "Scheme"; 8 | 9 | public SchemeLanguage() 10 | { 11 | super(ID); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/schemely/lexer/TokenSets.java: -------------------------------------------------------------------------------- 1 | package schemely.lexer; 2 | 3 | import com.intellij.psi.tree.TokenSet; 4 | 5 | 6 | public class TokenSets implements Tokens 7 | { 8 | // TODO CMF 9 | public static final TokenSet REFERENCE_NAMES = TokenSet.create(Tokens.IDENTIFIER); 10 | } 11 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /src/schemely/psi/impl/SchemeLiteral.java: -------------------------------------------------------------------------------- 1 | package schemely.psi.impl; 2 | 3 | import com.intellij.lang.ASTNode; 4 | 5 | 6 | public class SchemeLiteral extends SchemePsiElementBase 7 | { 8 | public SchemeLiteral(ASTNode node) 9 | { 10 | super(node, "SchemeLiteral"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/schemely/repl/REPLProvider.java: -------------------------------------------------------------------------------- 1 | package schemely.repl; 2 | 3 | import com.intellij.openapi.module.Module; 4 | import com.intellij.openapi.project.Project; 5 | 6 | /** 7 | * @author Colin Fleming 8 | */ 9 | public interface REPLProvider 10 | { 11 | boolean isSupported(); 12 | 13 | void createREPL(Project project, Module module); 14 | } 15 | -------------------------------------------------------------------------------- /src/schemely/scheme/sisc/psi/SISCPointerDef.java: -------------------------------------------------------------------------------- 1 | package schemely.scheme.sisc.psi; 2 | 3 | import com.intellij.lang.ASTNode; 4 | import schemely.psi.impl.SchemePsiElementBase; 5 | 6 | 7 | public class SISCPointerDef extends SchemePsiElementBase 8 | { 9 | public SISCPointerDef(ASTNode node) 10 | { 11 | super(node, "SISCPointerDef"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/schemely/scheme/sisc/psi/SISCPointerRef.java: -------------------------------------------------------------------------------- 1 | package schemely.scheme.sisc.psi; 2 | 3 | import com.intellij.lang.ASTNode; 4 | import schemely.psi.impl.SchemePsiElementBase; 5 | 6 | 7 | public class SISCPointerRef extends SchemePsiElementBase 8 | { 9 | public SISCPointerRef(ASTNode node) 10 | { 11 | super(node, "SISCPointerRef"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/schemely/psi/api/SchemeBraced.java: -------------------------------------------------------------------------------- 1 | package schemely.psi.api; 2 | 3 | import com.intellij.psi.PsiElement; 4 | import org.jetbrains.annotations.NotNull; 5 | import org.jetbrains.annotations.Nullable; 6 | 7 | 8 | public interface SchemeBraced extends SchemePsiElement 9 | { 10 | @NotNull 11 | PsiElement getFirstBrace(); 12 | 13 | @Nullable 14 | PsiElement getLastBrace(); 15 | } 16 | -------------------------------------------------------------------------------- /test/schemely/TestUtil.java: -------------------------------------------------------------------------------- 1 | package schemely; 2 | 3 | /** 4 | * @author Colin Fleming 5 | */ 6 | public class TestUtil 7 | { 8 | public static Object[][] testArray(T... items) 9 | { 10 | Object[][] ret = new Object[items.length][]; 11 | for (int i = 0; i < items.length; i++) 12 | { 13 | ret[i] = new Object[] { items[i] }; 14 | } 15 | return ret; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/schemely/parser/SchemePsiCreator.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 | 8 | 9 | public interface SchemePsiCreator 10 | { 11 | PsiElement createElement(ASTNode node); 12 | 13 | PsiFile createFile(FileViewProvider viewProvider); 14 | } 15 | -------------------------------------------------------------------------------- /src/schemely/psi/stubs/api/SchemeFileStub.java: -------------------------------------------------------------------------------- 1 | package schemely.psi.stubs.api; 2 | 3 | import com.intellij.psi.stubs.PsiFileStub; 4 | import com.intellij.util.io.StringRef; 5 | import schemely.psi.impl.SchemeFile; 6 | 7 | 8 | public interface SchemeFileStub extends PsiFileStub 9 | { 10 | StringRef getPackageName(); 11 | 12 | StringRef getName(); 13 | 14 | boolean isClassDefinition(); 15 | } 16 | 17 | -------------------------------------------------------------------------------- /src/schemely/scheme/sisc/parser/SISCAST.java: -------------------------------------------------------------------------------- 1 | package schemely.scheme.sisc.parser; 2 | 3 | import com.intellij.psi.tree.IElementType; 4 | import schemely.parser.SchemeElementType; 5 | 6 | /** 7 | * @author Colin Fleming 8 | */ 9 | public interface SISCAST 10 | { 11 | final IElementType PTR_DEF = new SchemeElementType("pointer def"); 12 | final IElementType PTR_REF = new SchemeElementType("pointer ref"); 13 | } 14 | -------------------------------------------------------------------------------- /src/schemely/highlighter/SchemeEditorHighlighter.java: -------------------------------------------------------------------------------- 1 | package schemely.highlighter; 2 | 3 | import com.intellij.openapi.editor.colors.EditorColorsScheme; 4 | import com.intellij.openapi.editor.ex.util.LexerEditorHighlighter; 5 | 6 | 7 | public class SchemeEditorHighlighter extends LexerEditorHighlighter 8 | { 9 | public SchemeEditorHighlighter(EditorColorsScheme scheme) 10 | { 11 | super(new SchemeSyntaxHighlighter(), scheme); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /resources/fileTemplates/j2ee/SchemeFile.clj.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 11 | 12 |
6 | 7 | This is a built-in template used by IDEA each time you create a 8 | Scheme file 9 | 10 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /src/schemely/scheme/sisc/lexer/SISCTokens.java: -------------------------------------------------------------------------------- 1 | package schemely.scheme.sisc.lexer; 2 | 3 | import com.intellij.psi.tree.IElementType; 4 | import schemely.parser.SchemeElementType; 5 | 6 | /** 7 | * @author Colin Fleming 8 | */ 9 | public interface SISCTokens 10 | { 11 | IElementType PTR_DEF = new SchemeElementType("pointer def"); 12 | IElementType PTR_REF = new SchemeElementType("pointer ref"); 13 | IElementType SYNTAX_QUOTE = new SchemeElementType("syntax quote"); 14 | } 15 | -------------------------------------------------------------------------------- /src/schemely/file/SchemeFileTypeLoader.java: -------------------------------------------------------------------------------- 1 | package schemely.file; 2 | 3 | import com.intellij.openapi.fileTypes.FileTypeConsumer; 4 | import com.intellij.openapi.fileTypes.FileTypeFactory; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | public class SchemeFileTypeLoader extends FileTypeFactory 8 | { 9 | public void createFileTypes(@NotNull FileTypeConsumer consumer) 10 | { 11 | consumer.consume(SchemeFileType.SCHEME_FILE_TYPE, SchemeFileType.SCHEME_EXTENSIONS); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/schemely/repl/SchemeConsoleView.java: -------------------------------------------------------------------------------- 1 | package schemely.repl; 2 | 3 | import com.intellij.openapi.project.Project; 4 | 5 | public class SchemeConsoleView extends LanguageConsoleViewImpl 6 | { 7 | public SchemeConsoleView(Project project, String title, ConsoleHistoryModel historyModel) 8 | { 9 | super(project, new SchemeConsole(project, title, historyModel)); 10 | } 11 | 12 | public SchemeConsole getConsole() 13 | { 14 | return (SchemeConsole) super.getConsole(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/schemely/parser/SchemeElementType.java: -------------------------------------------------------------------------------- 1 | package schemely.parser; 2 | 3 | import com.intellij.psi.tree.IElementType; 4 | import schemely.file.SchemeFileType; 5 | 6 | public class SchemeElementType extends IElementType 7 | { 8 | private final String name; 9 | 10 | public SchemeElementType(String debugName) 11 | { 12 | super(debugName, SchemeFileType.SCHEME_LANGUAGE); 13 | name = debugName; 14 | } 15 | 16 | public String getName() 17 | { 18 | return name; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/schemely/scheme/REPLException.java: -------------------------------------------------------------------------------- 1 | package schemely.scheme; 2 | 3 | /** 4 | * @author Colin Fleming 5 | */ 6 | public class REPLException extends Exception 7 | { 8 | public REPLException() 9 | { 10 | } 11 | 12 | public REPLException(String message) 13 | { 14 | super(message); 15 | } 16 | 17 | public REPLException(String message, Throwable cause) 18 | { 19 | super(message, cause); 20 | } 21 | 22 | public REPLException(Throwable cause) 23 | { 24 | super(cause); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/schemely/repl/UnsupportedREPLProvider.java: -------------------------------------------------------------------------------- 1 | package schemely.repl; 2 | 3 | import com.intellij.openapi.module.Module; 4 | import com.intellij.openapi.project.Project; 5 | 6 | /** 7 | * @author Colin Fleming 8 | */ 9 | public class UnsupportedREPLProvider implements REPLProvider 10 | { 11 | @Override 12 | public boolean isSupported() 13 | { 14 | return false; 15 | } 16 | 17 | @Override 18 | public void createREPL(Project project, Module module) 19 | { 20 | throw new UnsupportedOperationException(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/schemely/compiler/SchemeCompilerSettingsFactory.java: -------------------------------------------------------------------------------- 1 | package schemely.compiler; 2 | 3 | import com.intellij.compiler.CompilerSettingsFactory; 4 | import com.intellij.openapi.options.Configurable; 5 | import com.intellij.openapi.project.Project; 6 | 7 | /** 8 | * @author Colin Fleming 9 | */ 10 | public class SchemeCompilerSettingsFactory implements CompilerSettingsFactory 11 | { 12 | public Configurable create(Project project) 13 | { 14 | return new SchemeCompilerConfigurable(SchemeCompilerSettings.getInstance(project)); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/schemely/psi/stubs/index/SchemeClassNameIndex.java: -------------------------------------------------------------------------------- 1 | package schemely.psi.stubs.index; 2 | 3 | import com.intellij.psi.stubs.StringStubIndexExtension; 4 | import com.intellij.psi.stubs.StubIndexKey; 5 | import schemely.psi.impl.SchemeFile; 6 | 7 | 8 | public class SchemeClassNameIndex extends StringStubIndexExtension 9 | { 10 | public static final StubIndexKey KEY = StubIndexKey.createIndexKey("scm.class"); 11 | 12 | public StubIndexKey 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 | 24 | 25 | 28 | 29 | 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 | 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 | 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 theClass; 65 | 66 | public ParseTestCase(String contents, Class 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 | 6 | 7 | 8 | 9 | 10 | 26 | 27 | 29 | 30 | http://www.w3.org/1999/xhtml 31 | 32 | 33 | 34 | 35 | 36 | 54 | 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 |

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 | 59 | 60 | 61 | 62 | 63 | 64 | 65 |
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 | } --------------------------------------------------------------------------------