diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 52bf9ab9..27d7e1cd 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,8 +2,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -43,15 +151,16 @@ - + @@ -70,6 +179,13 @@ + + + + + + + @@ -82,7 +198,6 @@ - @@ -151,16 +266,18 @@ + - - + + - + @@ -176,7 +293,7 @@ - + @@ -211,29 +328,71 @@ + + + + + + + + + + + + + + + - - + + - + + + + + + + + + + + + + + + + + - - + + + + + + + + + - - + + - - + + + + + + diff --git a/.travis.yml b/.travis.yml index 221951e4..ffbf18ed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,7 +36,7 @@ jobs: - cd $TRAVIS_BUILD_DIR/extensions/vscode - ./gradlew vscodeExtension - cd $TRAVIS_BUILD_DIR - - cp -r plugins/com.yakindu.solidity.ide/target/languageserver extensions/theia/xtext-dsl-extension/lsp + - cp -r plugins/com.yakindu.solidity.ide/target/languageserver extensions/theia/xtext-dsl-extension/languageserver - cd extensions/theia/ - yarn install - cd $TRAVIS_BUILD_DIR diff --git a/extensions/theia/.gitignore b/extensions/theia/.gitignore index 01d025ab..bbe6dca5 100644 --- a/extensions/theia/.gitignore +++ b/extensions/theia/.gitignore @@ -6,5 +6,5 @@ */lsp/ */examples/ /node_modules/ -/xtext-dsl-extension/lsp +/xtext-dsl-extension/languageserver /com.yakindu.solidity.web.ide.docker.tar.gz diff --git a/extensions/theia/xtext-dsl-extension/package.json b/extensions/theia/xtext-dsl-extension/package.json index 32b64c14..5b472886 100644 --- a/extensions/theia/xtext-dsl-extension/package.json +++ b/extensions/theia/xtext-dsl-extension/package.json @@ -19,7 +19,7 @@ }, "scripts": { "prepare": "yarn run clean && yarn run build", - "copy-ls": "rimraf lsp && mkdir lsp && cp -r ../../../../plugins/com.yakindu.solidity.ide/target/languageserver/* ./lsp/", + "copy-ls": "rimraf lsp && mkdir languageserver && cp -r ../../../../plugins/com.yakindu.solidity.ide/target/languageserver/* ./languageserver/", "clean": "rimraf lib", "build": "tsc", "local": "tsc && yarn run copy-ls", diff --git a/extensions/theia/xtext-dsl-extension/src/node/solidity-contribution.ts b/extensions/theia/xtext-dsl-extension/src/node/solidity-contribution.ts index bc0f5174..3ebd9882 100644 --- a/extensions/theia/xtext-dsl-extension/src/node/solidity-contribution.ts +++ b/extensions/theia/xtext-dsl-extension/src/node/solidity-contribution.ts @@ -76,8 +76,8 @@ export class SolidityContribution extends BaseLanguageServerContribution { } else { const ops = os.platform(); - let command = path.resolve(__dirname, '../../lsp/bin/solidity-ls'); - if (ops.toLowerCase().includes("win")){ + let command = path.resolve(__dirname, '../../languageserver/bin/solidity-ls'); + if (ops == "win32"){ command += ".bat" } diff --git a/features/com.yakindu.solidity.solc.feature/feature.xml b/features/com.yakindu.solidity.solc.feature/feature.xml index 4e64e6f7..52af5579 100644 --- a/features/com.yakindu.solidity.solc.feature/feature.xml +++ b/features/com.yakindu.solidity.solc.feature/feature.xml @@ -712,7 +712,7 @@ Public License instead of this License. But first, please read unpack="false"/> + xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 4.0.0 com.yakindu.solidity @@ -35,13 +36,13 @@ com.yakindu.solidity - com.yakindu.solidity.solc.mac.fragment + com.yakindu.solidity.solc.macosx.fragment 0.7.3-SNAPSHOT true com.yakindu.solidity - com.yakindu.solidity.solc.win.fragment + com.yakindu.solidity.solc.win32.fragment 0.7.3-SNAPSHOT true @@ -83,7 +84,6 @@ - org.eclipse.xtend xtend-maven-plugin @@ -95,73 +95,6 @@ - - org.apache.maven.plugins - maven-dependency-plugin - 3.0.1 - - - copy-dependencies - package - - copy-dependencies - - - ${project.build.directory}/libs - false - false - true - true - - com.ibm.icu, - org.apache.ant, - org.apache.commons.lang, - org.apache.commons.logging, - org.eclipse.core.commands, - org.eclipse.core.contenttype, - org.eclipse.core.expressions, - org.eclipse.core.filesystem, - org.eclipse.core.variables, - org.eclipse.debug.core, - org.eclipse.emf.codegen.ecore, - org.eclipse.emf.codegen, - org.eclipse.emf.mwe.core, - org.eclipse.emf.mwe.utils, - org.eclipse.emf.mwe2.lib, - org.eclipse.emf.mwe2.runtime, - org.eclipse.equinox.app, - org.eclipse.equinox.registry, - org.eclipse.jdt.core, - org.eclipse.jdt.debug, - org.eclipse.jdt.launching, - org.eclipse.text, - org.eclipse.xtend.typesystem.emf, - org.eclipse.xtend, - - - - - - - com.googlecode.addjars-maven-plugin - addjars-maven-plugin - 1.0.5 - - - package - - add-jars - - - - - ${project.build.directory}/libs - - - - - - org.codehaus.mojo appassembler-maven-plugin @@ -173,26 +106,72 @@ assemble + true + true ${project.build.directory}/languageserver flat - true - + solidity-ls - - org.eclipse.xtext.ide.server.ServerLauncher - + com.yakindu.solidity.ide.LanguageServerLauncher + + + -trace + -log + + + -compiler repo/com.yakindu.solidity.solc.\${os}.fragment/compiler/solc + + + maven-antrun-plugin + 1.8 + + + package + + + + + + + + + + + + + + + + + + + + + run + + + + diff --git a/plugins/com.yakindu.solidity.ide/src/com/yakindu/solidity/ide/LanguageServerLauncher.java b/plugins/com.yakindu.solidity.ide/src/com/yakindu/solidity/ide/LanguageServerLauncher.java new file mode 100644 index 00000000..74fde188 --- /dev/null +++ b/plugins/com.yakindu.solidity.ide/src/com/yakindu/solidity/ide/LanguageServerLauncher.java @@ -0,0 +1,95 @@ +package com.yakindu.solidity.ide; + +import java.io.File; +import java.io.IOException; + +import org.apache.commons.cli.BasicParser; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.Options; +import org.apache.commons.lang.SystemUtils; +import org.eclipse.xtext.ide.server.ServerLauncher; +import org.eclipse.xtext.ide.server.ServerModule; +import org.eclipse.xtext.util.Modules2; + +import com.google.inject.Guice; +import com.yakindu.solidity.SolidityRuntimeModule; +import com.yakindu.solidity.solc.preferences.ICompilerPreferences; + +/** + * @author Jonathan Thoene - Initial contribution and API + */ +public class LanguageServerLauncher { + + public static final String COMPILER = "-compiler"; + + public static void main(String[] args) throws InterruptedException, IOException { + try { + Options o = new Options(); + o.addOption(ServerLauncher.LOG.substring(1), false, "Log"); + o.addOption(ServerLauncher.TRACE.substring(1), false, "Trace"); + o.addOption(ServerLauncher.NO_VALIDATE.substring(1), false, "No Validate"); + o.addOption(COMPILER.substring(1), true, "Path to Solc Compiler (relative to working dir)"); + CommandLineParser p = new BasicParser(); + CommandLine cmd = p.parse(o, args); + if (cmd.hasOption(COMPILER.substring(1))) { + String compilerPath = cmd.getOptionValue(COMPILER.substring(1)).replace("${os}", getOS()); + String absoluteCompilerPath = getWorkDir() + compilerPath; + ICompilerPreferences prefs = Guice + .createInjector(Modules2.mixin(new SolidityRuntimeModule(), new SolidityIdeModule())) + .getInstance(ICompilerPreferences.class); + prefs.getPreferences().put(ICompilerPreferences.COMPILER_PATH, absoluteCompilerPath); + } + } catch (Exception e) { + e.printStackTrace(); + } + ServerLauncher.launch(LanguageServerLauncher.class.getName(), args, new ServerModule()); + /* + * Injector injector = Guice.createInjector(new ServerModule()); + * LanguageServerImpl languageServer = + * injector.getInstance(LanguageServerImpl.class); Function wrapper = consumer -> { return message -> { + * System.out.println(message); consumer.consume(message); }; }; + * Launcher launcher = createSocketLauncher(languageServer, + * LanguageClient.class, new InetSocketAddress("localhost", 5007), + * Executors.newCachedThreadPool(), wrapper); + * languageServer.connect(launcher.getRemoteProxy()); Future future = + * launcher.startListening(); while (!future.isDone()) { Thread.sleep(10_000l); + * } + */ + } + + private static String getWorkDir() throws IOException { + // TODO: app workdir should be configured in Maven to be language server dir, + // not theia app dir, so we do not have to compensate this here. + String appDir = new File(".").getCanonicalPath(); + return appDir.substring(0, appDir.indexOf("app")) + "xtext-dsl-extension/languageserver/"; + } + + private static CharSequence getOS() { + if (SystemUtils.IS_OS_LINUX) { + return "linux"; + } else if (SystemUtils.IS_OS_WINDOWS) { + return "win32"; + } else if (SystemUtils.IS_OS_MAC || SystemUtils.IS_OS_MAC_OSX) { + return "macosx"; + } else { + throw new IllegalArgumentException("Unsupported OS"); + } + } + + /* + * static Launcher createSocketLauncher(Object localService, Class + * remoteInterface, SocketAddress socketAddress, ExecutorService + * executorService, Function wrapper) throws + * IOException { AsynchronousServerSocketChannel serverSocket = + * AsynchronousServerSocketChannel.open().bind(socketAddress); + * AsynchronousSocketChannel socketChannel; try { socketChannel = + * serverSocket.accept().get(); return Launcher.createIoLauncher(localService, + * remoteInterface, Channels.newInputStream(socketChannel), + * Channels.newOutputStream(socketChannel), executorService, wrapper); } catch + * (InterruptedException | ExecutionException e) { e.printStackTrace(); } return + * null; } + */ + +} diff --git a/plugins/com.yakindu.solidity.ide/src/com/yakindu/solidity/ide/RunServer.java b/plugins/com.yakindu.solidity.ide/src/com/yakindu/solidity/ide/RunServer.java deleted file mode 100644 index 9d957975..00000000 --- a/plugins/com.yakindu.solidity.ide/src/com/yakindu/solidity/ide/RunServer.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.yakindu.solidity.ide; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.nio.channels.AsynchronousServerSocketChannel; -import java.nio.channels.AsynchronousSocketChannel; -import java.nio.channels.Channels; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.function.Function; - -import org.eclipse.lsp4j.jsonrpc.Launcher; -import org.eclipse.lsp4j.jsonrpc.MessageConsumer; -import org.eclipse.lsp4j.services.LanguageClient; -import org.eclipse.xtext.ide.server.LanguageServerImpl; -import org.eclipse.xtext.ide.server.ServerModule; - -import com.google.inject.Guice; -import com.google.inject.Injector; - -/** - * @author Jonathan Thoene - Initial contribution and API - */ -public class RunServer { - - public static void main(String[] args) throws InterruptedException, IOException { - Injector injector = Guice.createInjector(new ServerModule()); - LanguageServerImpl languageServer = injector.getInstance(LanguageServerImpl.class); - Function wrapper = consumer -> { - return message -> { - System.out.println(message); - consumer.consume(message); - }; - }; - Launcher launcher = createSocketLauncher(languageServer, LanguageClient.class, new InetSocketAddress("localhost", 5007), Executors.newCachedThreadPool(), wrapper); - languageServer.connect(launcher.getRemoteProxy()); - Future future = launcher.startListening(); - while (!future.isDone()) { - Thread.sleep(10_000l); - } - } - - static Launcher createSocketLauncher(Object localService, Class remoteInterface, SocketAddress socketAddress, ExecutorService executorService, Function wrapper) throws IOException { - AsynchronousServerSocketChannel serverSocket = AsynchronousServerSocketChannel.open().bind(socketAddress); - AsynchronousSocketChannel socketChannel; - try { - socketChannel = serverSocket.accept().get(); - return Launcher.createIoLauncher(localService, remoteInterface, Channels.newInputStream(socketChannel), Channels.newOutputStream(socketChannel), executorService, wrapper); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - return null; - } - -} diff --git a/plugins/com.yakindu.solidity.ide/src/com/yakindu/solidity/ide/SolidityIdeModule.xtend b/plugins/com.yakindu.solidity.ide/src/com/yakindu/solidity/ide/SolidityIdeModule.xtend index fd5d37f9..48d11762 100644 --- a/plugins/com.yakindu.solidity.ide/src/com/yakindu/solidity/ide/SolidityIdeModule.xtend +++ b/plugins/com.yakindu.solidity.ide/src/com/yakindu/solidity/ide/SolidityIdeModule.xtend @@ -3,9 +3,29 @@ */ package com.yakindu.solidity.ide +import com.google.inject.Binder +import com.yakindu.solidity.IWorkspaceResourceResolver +import com.yakindu.solidity.ide.internal.CustomContentAssistService +import com.yakindu.solidity.ide.internal.SolidityIdeCodeActionService +import org.eclipse.xtext.ide.server.codeActions.ICodeActionService2 +import org.eclipse.xtext.ide.server.contentassist.ContentAssistService /** * Use this class to register ide components. */ class SolidityIdeModule extends AbstractSolidityIdeModule { + + override configure(Binder binder) { + super.configure(binder); + binder.bind(IWorkspaceResourceResolver).to(WorkspaceManagerResourceResolver); + } + + // workaround for https://github.com/eclipse/xtext-eclipse/issues/834 + def Class bindContentAssistService() { + return CustomContentAssistService + } + + def Class bindICodeActionService() { + return SolidityIdeCodeActionService + } } diff --git a/plugins/com.yakindu.solidity.ide/src/com/yakindu/solidity/ide/SolidityIdeSetup.xtend b/plugins/com.yakindu.solidity.ide/src/com/yakindu/solidity/ide/SolidityIdeSetup.xtend index 59460c9b..32a04a50 100644 --- a/plugins/com.yakindu.solidity.ide/src/com/yakindu/solidity/ide/SolidityIdeSetup.xtend +++ b/plugins/com.yakindu.solidity.ide/src/com/yakindu/solidity/ide/SolidityIdeSetup.xtend @@ -17,7 +17,6 @@ package com.yakindu.solidity.ide import com.google.inject.Guice import com.yakindu.solidity.SolidityRuntimeModule import com.yakindu.solidity.SolidityStandaloneSetup -import com.yakindu.solidity.ide.internal.SolidityIdeModule import org.eclipse.xtext.util.Modules2 /** diff --git a/plugins/com.yakindu.solidity.ide/src/com/yakindu/solidity/ide/WorkspaceManagerResourceResolver.java b/plugins/com.yakindu.solidity.ide/src/com/yakindu/solidity/ide/WorkspaceManagerResourceResolver.java new file mode 100644 index 00000000..e254427c --- /dev/null +++ b/plugins/com.yakindu.solidity.ide/src/com/yakindu/solidity/ide/WorkspaceManagerResourceResolver.java @@ -0,0 +1,27 @@ +package com.yakindu.solidity.ide; + +import java.io.File; +import java.net.URI; + +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.xtext.ide.server.UriExtensions; +import org.eclipse.xtext.workspace.IProjectConfig; +import org.eclipse.xtext.workspace.ProjectConfigProvider; + +import com.google.inject.Inject; +import com.yakindu.solidity.IWorkspaceResourceResolver; + +@SuppressWarnings("restriction") +public class WorkspaceManagerResourceResolver implements IWorkspaceResourceResolver { + + @Inject + UriExtensions uriExtensions; + + @Override + public File resolve(Resource resource) { + IProjectConfig projectConfig = new ProjectConfigProvider().getProjectConfig(resource.getResourceSet()); + String absoluteResourcePath = projectConfig.getPath().scheme() + ":" + resource.getURI().toFileString(); + return new File(URI.create(absoluteResourcePath)); + } + +} diff --git a/plugins/com.yakindu.solidity.ide/src/com/yakindu/solidity/ide/internal/SolidityIdeCodeActionService.xtend b/plugins/com.yakindu.solidity.ide/src/com/yakindu/solidity/ide/internal/SolidityIdeCodeActionService.xtend index bb4151b4..6b3fb863 100644 --- a/plugins/com.yakindu.solidity.ide/src/com/yakindu/solidity/ide/internal/SolidityIdeCodeActionService.xtend +++ b/plugins/com.yakindu.solidity.ide/src/com/yakindu/solidity/ide/internal/SolidityIdeCodeActionService.xtend @@ -1,38 +1,42 @@ package com.yakindu.solidity.ide.internal import com.google.inject.Inject -import com.google.inject.name.Named -import com.yakindu.solidity.SolidityVersion -import com.yakindu.solidity.validation.IssueCodes -import java.util.List import org.eclipse.emf.common.util.URI import org.eclipse.lsp4j.CodeAction -import org.eclipse.lsp4j.CodeActionParams -import org.eclipse.lsp4j.Command import org.eclipse.lsp4j.TextEdit import org.eclipse.lsp4j.WorkspaceEdit import org.eclipse.lsp4j.jsonrpc.messages.Either -import org.eclipse.xtext.ide.server.Document -import org.eclipse.xtext.ide.server.codeActions.ICodeActionService -import org.eclipse.xtext.resource.XtextResource -import org.eclipse.xtext.util.CancelIndicator +import org.eclipse.xtext.ide.server.codeActions.ICodeActionService2 +import com.yakindu.solidity.SolidityVersion +import com.google.inject.name.Named -class SolidityIdeCodeActionService implements ICodeActionService { +import static com.yakindu.solidity.validation.IssueCodes.* + + +/** + * @author Jonathan Thoene - Initial contribution and API + */ +class SolidityIdeCodeActionService implements ICodeActionService2 { @Inject @Named(SolidityVersion.SOLIDITY_VERSION) String solcVersion - override List> getCodeActions(Document document, XtextResource resource, - CodeActionParams params, CancelIndicator indicator) { + protected def addTextEdit(WorkspaceEdit edit, URI uri, TextEdit... textEdit) { + edit.changes.put(uri.toString, textEdit) + } + + override getCodeActions(Options options) { + val resource = options.resource + val params = options.codeActionParams val actions = newArrayList for (d : params.context.diagnostics) { - if (d.code == IssueCodes.WARNING_SOLIDITY_VERSION_NOT_THE_DEFAULT) { + if (d.code.hasSolution) { actions += Either.forRight(new CodeAction => [ - title = '''Change to «solcVersion»''' + title = d.code.label diagnostics = #[d] edit = new WorkspaceEdit() => [ addTextEdit(resource.URI, new TextEdit => [ range = d.range - newText = solcVersion + newText = d.code.fix ]) ] ]) @@ -40,9 +44,24 @@ class SolidityIdeCodeActionService implements ICodeActionService { } return actions } - - protected def addTextEdit(WorkspaceEdit edit, URI uri, TextEdit... textEdit) { - edit.changes.put(uri.toString, textEdit) + + + def String getLabel(String issueCode) { + switch (issueCode) { + case WARNING_SOLIDITY_VERSION_NOT_THE_DEFAULT : '''Change version to «solcVersion»''' + default: "" + } + } + + def String getFix(String issueCode) { + switch (issueCode) { + case WARNING_SOLIDITY_VERSION_NOT_THE_DEFAULT : solcVersion + default: "" + } + } + + def boolean hasSolution(String issueCode) { + return !issueCode.label.nullOrEmpty } } diff --git a/plugins/com.yakindu.solidity.ide/src/com/yakindu/solidity/ide/internal/SolidityIdeModule.xtend b/plugins/com.yakindu.solidity.ide/src/com/yakindu/solidity/ide/internal/SolidityIdeModule.xtend deleted file mode 100644 index 99649de3..00000000 --- a/plugins/com.yakindu.solidity.ide/src/com/yakindu/solidity/ide/internal/SolidityIdeModule.xtend +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright (c) 2017 committers of YAKINDU and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Andreas Muelder - Itemis AG - initial API and implementation - * Karsten Thoms - Itemis AG - initial API and implementation - * Florian Antony - Itemis AG - initial API and implementation - * committers of YAKINDU - * - */ -package com.yakindu.solidity.ide.internal - -import com.yakindu.solidity.ide.AbstractSolidityIdeModule -import org.eclipse.xtext.ide.server.contentassist.ContentAssistService -import org.eclipse.xtext.ide.server.codeActions.ICodeActionService - -/** - * - * - * Use this class to register ide components. - * @author Andreas Muelder - Initial contribution and API - * @author Florian Antony - */ -class SolidityIdeModule extends AbstractSolidityIdeModule { - // workaround for https://github.com/eclipse/xtext-eclipse/issues/834 - def Class bindContentAssistService() { - return CustomContentAssistService - } - - def Class bindICodeActionService() { - return SolidityIdeCodeActionService - } -} diff --git a/plugins/com.yakindu.solidity.solc.linux.fragment/META-INF/MANIFEST.MF b/plugins/com.yakindu.solidity.solc.linux.fragment/META-INF/MANIFEST.MF index 408f5621..976f8582 100644 --- a/plugins/com.yakindu.solidity.solc.linux.fragment/META-INF/MANIFEST.MF +++ b/plugins/com.yakindu.solidity.solc.linux.fragment/META-INF/MANIFEST.MF @@ -8,4 +8,5 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Export-Package: com.yakindu.solidity.solc Bundle-Vendor: YAKINDU Automatic-Module-Name: com.yakindu.solidity.solc.linux.fragment - +Eclipse-PlatformFilter: (& (osgi.ws=gtk) (osgi.os=linux) (osgi.arch=x86_64) ) +Eclipse-BundleShape: dir diff --git a/plugins/com.yakindu.solidity.solc.mac.fragment/.classpath b/plugins/com.yakindu.solidity.solc.macosx.fragment/.classpath similarity index 100% rename from plugins/com.yakindu.solidity.solc.mac.fragment/.classpath rename to plugins/com.yakindu.solidity.solc.macosx.fragment/.classpath diff --git a/plugins/com.yakindu.solidity.solc.mac.fragment/.project b/plugins/com.yakindu.solidity.solc.macosx.fragment/.project similarity index 91% rename from plugins/com.yakindu.solidity.solc.mac.fragment/.project rename to plugins/com.yakindu.solidity.solc.macosx.fragment/.project index d916d31a..27f8d96b 100644 --- a/plugins/com.yakindu.solidity.solc.mac.fragment/.project +++ b/plugins/com.yakindu.solidity.solc.macosx.fragment/.project @@ -1,6 +1,6 @@ - com.yakindu.solidity.solc.mac.fragment + com.yakindu.solidity.solc.macosx.fragment diff --git a/plugins/com.yakindu.solidity.solc.mac.fragment/.settings/org.eclipse.jdt.core.prefs b/plugins/com.yakindu.solidity.solc.macosx.fragment/.settings/org.eclipse.jdt.core.prefs similarity index 100% rename from plugins/com.yakindu.solidity.solc.mac.fragment/.settings/org.eclipse.jdt.core.prefs rename to plugins/com.yakindu.solidity.solc.macosx.fragment/.settings/org.eclipse.jdt.core.prefs diff --git a/plugins/com.yakindu.solidity.solc.mac.fragment/META-INF/MANIFEST.MF b/plugins/com.yakindu.solidity.solc.macosx.fragment/META-INF/MANIFEST.MF similarity index 70% rename from plugins/com.yakindu.solidity.solc.mac.fragment/META-INF/MANIFEST.MF rename to plugins/com.yakindu.solidity.solc.macosx.fragment/META-INF/MANIFEST.MF index 6440325b..e3ae08fc 100644 --- a/plugins/com.yakindu.solidity.solc.mac.fragment/META-INF/MANIFEST.MF +++ b/plugins/com.yakindu.solidity.solc.macosx.fragment/META-INF/MANIFEST.MF @@ -1,11 +1,12 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Solidity Tools Solc Compiler for MacOSX -Bundle-SymbolicName: com.yakindu.solidity.solc.mac.fragment +Bundle-SymbolicName: com.yakindu.solidity.solc.macosx.fragment Bundle-Version: 0.7.3.qualifier Bundle-Vendor: YAKINDU Fragment-Host: com.yakindu.solidity.solc Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Automatic-Module-Name: com.yakindu.solidity.solc.mac.fragment Export-Package: com.yakindu.solidity.solc +Eclipse-PlatformFilter: (& (osgi.os=macosx) (osgi.ws=cocoa) (osgi.arch=x86_64) ) diff --git a/plugins/com.yakindu.solidity.solc.mac.fragment/build.properties b/plugins/com.yakindu.solidity.solc.macosx.fragment/build.properties similarity index 100% rename from plugins/com.yakindu.solidity.solc.mac.fragment/build.properties rename to plugins/com.yakindu.solidity.solc.macosx.fragment/build.properties diff --git a/plugins/com.yakindu.solidity.solc.mac.fragment/compiler/solc b/plugins/com.yakindu.solidity.solc.macosx.fragment/compiler/solc similarity index 100% rename from plugins/com.yakindu.solidity.solc.mac.fragment/compiler/solc rename to plugins/com.yakindu.solidity.solc.macosx.fragment/compiler/solc diff --git a/plugins/com.yakindu.solidity.solc.mac.fragment/pom.xml b/plugins/com.yakindu.solidity.solc.macosx.fragment/pom.xml similarity index 94% rename from plugins/com.yakindu.solidity.solc.mac.fragment/pom.xml rename to plugins/com.yakindu.solidity.solc.macosx.fragment/pom.xml index f72a5eb8..c98b2c8d 100644 --- a/plugins/com.yakindu.solidity.solc.mac.fragment/pom.xml +++ b/plugins/com.yakindu.solidity.solc.macosx.fragment/pom.xml @@ -9,7 +9,7 @@ 0.7.3-SNAPSHOT ../../releng/com.yakindu.solidity.releng/pom.xml - com.yakindu.solidity.solc.mac.fragment + com.yakindu.solidity.solc.macosx.fragment com.yakindu.solidity eclipse-plugin diff --git a/plugins/com.yakindu.solidity.solc.mac.fragment/src/com/yakindu/solidity/solc/SolidityCompiler.java b/plugins/com.yakindu.solidity.solc.macosx.fragment/src/com/yakindu/solidity/solc/SolidityCompiler.java similarity index 100% rename from plugins/com.yakindu.solidity.solc.mac.fragment/src/com/yakindu/solidity/solc/SolidityCompiler.java rename to plugins/com.yakindu.solidity.solc.macosx.fragment/src/com/yakindu/solidity/solc/SolidityCompiler.java diff --git a/plugins/com.yakindu.solidity.solc.win.fragment/.classpath b/plugins/com.yakindu.solidity.solc.win32.fragment/.classpath similarity index 100% rename from plugins/com.yakindu.solidity.solc.win.fragment/.classpath rename to plugins/com.yakindu.solidity.solc.win32.fragment/.classpath diff --git a/plugins/com.yakindu.solidity.solc.win.fragment/.project b/plugins/com.yakindu.solidity.solc.win32.fragment/.project similarity index 91% rename from plugins/com.yakindu.solidity.solc.win.fragment/.project rename to plugins/com.yakindu.solidity.solc.win32.fragment/.project index 2515d63b..1a5b3d07 100644 --- a/plugins/com.yakindu.solidity.solc.win.fragment/.project +++ b/plugins/com.yakindu.solidity.solc.win32.fragment/.project @@ -1,6 +1,6 @@ - com.yakindu.solidity.solc.win.fragment + com.yakindu.solidity.solc.win32.fragment diff --git a/plugins/com.yakindu.solidity.solc.win.fragment/.settings/org.eclipse.core.resources.prefs b/plugins/com.yakindu.solidity.solc.win32.fragment/.settings/org.eclipse.core.resources.prefs similarity index 100% rename from plugins/com.yakindu.solidity.solc.win.fragment/.settings/org.eclipse.core.resources.prefs rename to plugins/com.yakindu.solidity.solc.win32.fragment/.settings/org.eclipse.core.resources.prefs diff --git a/plugins/com.yakindu.solidity.solc.win.fragment/.settings/org.eclipse.jdt.core.prefs b/plugins/com.yakindu.solidity.solc.win32.fragment/.settings/org.eclipse.jdt.core.prefs similarity index 100% rename from plugins/com.yakindu.solidity.solc.win.fragment/.settings/org.eclipse.jdt.core.prefs rename to plugins/com.yakindu.solidity.solc.win32.fragment/.settings/org.eclipse.jdt.core.prefs diff --git a/plugins/com.yakindu.solidity.solc.win.fragment/META-INF/MANIFEST.MF b/plugins/com.yakindu.solidity.solc.win32.fragment/META-INF/MANIFEST.MF similarity index 58% rename from plugins/com.yakindu.solidity.solc.win.fragment/META-INF/MANIFEST.MF rename to plugins/com.yakindu.solidity.solc.win32.fragment/META-INF/MANIFEST.MF index d221b104..6a4e0d6f 100644 --- a/plugins/com.yakindu.solidity.solc.win.fragment/META-INF/MANIFEST.MF +++ b/plugins/com.yakindu.solidity.solc.win32.fragment/META-INF/MANIFEST.MF @@ -1,10 +1,11 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Solidity Tools Solc Compiler for Windows -Bundle-SymbolicName: com.yakindu.solidity.solc.win.fragment +Bundle-SymbolicName: com.yakindu.solidity.solc.win32.fragment Bundle-Version: 0.7.3.qualifier Fragment-Host: com.yakindu.solidity.solc Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-Vendor: YAKINDU -Automatic-Module-Name: com.yakindu.solidity.solc.win.fragment +Automatic-Module-Name: com.yakindu.solidity.solc.win32.fragment Export-Package: com.yakindu.solidity.solc +Eclipse-PlatformFilter: (& (osgi.ws=win32) (osgi.os=win32) (osgi.arch=x86_64)) diff --git a/plugins/com.yakindu.solidity.solc.win.fragment/build.properties b/plugins/com.yakindu.solidity.solc.win32.fragment/build.properties similarity index 100% rename from plugins/com.yakindu.solidity.solc.win.fragment/build.properties rename to plugins/com.yakindu.solidity.solc.win32.fragment/build.properties diff --git a/plugins/com.yakindu.solidity.solc.win.fragment/compiler/msvcp140.dll b/plugins/com.yakindu.solidity.solc.win32.fragment/compiler/msvcp140.dll similarity index 100% rename from plugins/com.yakindu.solidity.solc.win.fragment/compiler/msvcp140.dll rename to plugins/com.yakindu.solidity.solc.win32.fragment/compiler/msvcp140.dll diff --git a/plugins/com.yakindu.solidity.solc.win.fragment/compiler/msvcp140_1.dll b/plugins/com.yakindu.solidity.solc.win32.fragment/compiler/msvcp140_1.dll similarity index 100% rename from plugins/com.yakindu.solidity.solc.win.fragment/compiler/msvcp140_1.dll rename to plugins/com.yakindu.solidity.solc.win32.fragment/compiler/msvcp140_1.dll diff --git a/plugins/com.yakindu.solidity.solc.win.fragment/compiler/msvcp140_2.dll b/plugins/com.yakindu.solidity.solc.win32.fragment/compiler/msvcp140_2.dll similarity index 100% rename from plugins/com.yakindu.solidity.solc.win.fragment/compiler/msvcp140_2.dll rename to plugins/com.yakindu.solidity.solc.win32.fragment/compiler/msvcp140_2.dll diff --git a/plugins/com.yakindu.solidity.solc.win.fragment/compiler/solc.exe b/plugins/com.yakindu.solidity.solc.win32.fragment/compiler/solc.exe similarity index 100% rename from plugins/com.yakindu.solidity.solc.win.fragment/compiler/solc.exe rename to plugins/com.yakindu.solidity.solc.win32.fragment/compiler/solc.exe diff --git a/plugins/com.yakindu.solidity.solc.win.fragment/pom.xml b/plugins/com.yakindu.solidity.solc.win32.fragment/pom.xml similarity index 94% rename from plugins/com.yakindu.solidity.solc.win.fragment/pom.xml rename to plugins/com.yakindu.solidity.solc.win32.fragment/pom.xml index 375162f2..c2630866 100644 --- a/plugins/com.yakindu.solidity.solc.win.fragment/pom.xml +++ b/plugins/com.yakindu.solidity.solc.win32.fragment/pom.xml @@ -9,7 +9,7 @@ 0.7.3-SNAPSHOT ../../releng/com.yakindu.solidity.releng/pom.xml - com.yakindu.solidity.solc.win.fragment + com.yakindu.solidity.solc.win32.fragment com.yakindu.solidity eclipse-plugin diff --git a/plugins/com.yakindu.solidity.solc.win.fragment/src/com/yakindu/solidity/solc/SolidityCompiler.java b/plugins/com.yakindu.solidity.solc.win32.fragment/src/com/yakindu/solidity/solc/SolidityCompiler.java similarity index 100% rename from plugins/com.yakindu.solidity.solc.win.fragment/src/com/yakindu/solidity/solc/SolidityCompiler.java rename to plugins/com.yakindu.solidity.solc.win32.fragment/src/com/yakindu/solidity/solc/SolidityCompiler.java diff --git a/plugins/com.yakindu.solidity.solc/META-INF/MANIFEST.MF b/plugins/com.yakindu.solidity.solc/META-INF/MANIFEST.MF index a374af5c..01647a22 100644 --- a/plugins/com.yakindu.solidity.solc/META-INF/MANIFEST.MF +++ b/plugins/com.yakindu.solidity.solc/META-INF/MANIFEST.MF @@ -7,9 +7,8 @@ Bundle-Vendor: YAKINDU Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Require-Bundle: org.yakindu.base.types, com.google.gson, - org.eclipse.core.runtime, - org.eclipse.core.resources, com.google.guava, + org.eclipse.core.runtime, org.eclipse.xtext Bundle-ActivationPolicy: lazy Bundle-Activator: com.yakindu.solidity.solc.SolidityCompilerActivator @@ -20,3 +19,4 @@ Export-Package: com.yakindu.solidity.solc, com.yakindu.solidity.solc.preferences, com.yakindu.solidity.solc.result Automatic-Module-Name: com.yakindu.solidity.solc +Eclipse-ExtensibleAPI: true diff --git a/plugins/com.yakindu.solidity.solc/build.properties b/plugins/com.yakindu.solidity.solc/build.properties index e9863e28..b476c1fb 100644 --- a/plugins/com.yakindu.solidity.solc/build.properties +++ b/plugins/com.yakindu.solidity.solc/build.properties @@ -2,4 +2,4 @@ source.. = src/ output.. = bin/ bin.includes = META-INF/,\ .,\ - plugin.xml + plugin.xml \ No newline at end of file diff --git a/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/ISolidityCompiler.java b/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/ISolidityCompiler.java index 57efb57c..520a8c38 100644 --- a/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/ISolidityCompiler.java +++ b/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/ISolidityCompiler.java @@ -14,10 +14,10 @@ */ package com.yakindu.solidity.solc; +import java.io.File; import java.util.Optional; import java.util.Set; -import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; import com.google.inject.ImplementedBy; @@ -31,7 +31,7 @@ @ImplementedBy(SolidityCompilerBase.class) public interface ISolidityCompiler { - public Optional compile(Set resources, IProgressMonitor progress); + public Optional compile(Set resources, IProgressMonitor progress); } \ No newline at end of file diff --git a/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/SolidityCompilerActivator.java b/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/SolidityCompilerActivator.java index 7142fb17..52cc8b3d 100644 --- a/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/SolidityCompilerActivator.java +++ b/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/SolidityCompilerActivator.java @@ -24,7 +24,7 @@ */ public class SolidityCompilerActivator extends Plugin { - public static final String PLUGIN_ID = "com.yakindu.solidity.compiler"; + public static final String PLUGIN_ID = "com.yakindu.solidity.solc"; private static SolidityCompilerActivator INSTANCE; diff --git a/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/SolidityCompilerBase.java b/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/SolidityCompilerBase.java index 2633fbfe..28ccf8e0 100644 --- a/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/SolidityCompilerBase.java +++ b/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/SolidityCompilerBase.java @@ -20,14 +20,10 @@ import java.io.OutputStreamWriter; import java.net.URL; import java.nio.charset.Charset; -import java.util.List; import java.util.Optional; import java.util.Set; import java.util.concurrent.TimeUnit; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; @@ -62,7 +58,7 @@ protected Path getPath() { } @Override - public Optional compile(Set filesToCompile, IProgressMonitor progress) { + public Optional compile(Set filesToCompile, IProgressMonitor progress) { if (filesToCompile.isEmpty() || progress.isCanceled()) { return Optional.empty(); } @@ -84,25 +80,14 @@ public Optional compile(Set filesToCompile, IProgress progress.done(); return Optional.empty(); } - } - protected Set getFilesToCompile(List uris) { - Set filesToCompile = Sets.newHashSet(); - for (URI uri : uris) { - IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(uri.toPlatformString(true)); - filesToCompile.add(resource); - filesToCompile.addAll(addImports(uri)); - } - return filesToCompile; - } - - protected Set addImports(URI uri) { + protected Set addImports(URI uri) { // TODO resolve uris to imported contracts return Sets.newHashSet(); } - protected void sendInput(OutputStream stream, Set filesToCompile) { + protected void sendInput(OutputStream stream, Set filesToCompile) { try (OutputStreamWriter writer = new OutputStreamWriter(stream, Charset.forName("UTF-8"));) { ParameterBuilder builder = new ParameterBuilder(); if (prefs.isWriteBINFile()) { @@ -114,10 +99,9 @@ protected void sendInput(OutputStream stream, Set filesToCompile) { if (prefs.isWriteASMFile()) { builder.addOutput(CompileOutputType.ASM.COMPILER_KEY); } - for (IResource resource : filesToCompile) { - if (resource instanceof IFile) { - IFile file = (IFile) resource; - builder.addSource(file.getLocation().lastSegment(), new Source(file)); + for (File resource : filesToCompile) { + if (resource.isFile()) { + builder.addSource(resource.getName(), new Source(resource)); } } builder.addOutput(CompileOutputType.GAS.COMPILER_KEY); @@ -131,10 +115,19 @@ protected void sendInput(OutputStream stream, Set filesToCompile) { protected String getCompilerPath() { Optional pathToCompiler = prefs.getCompilerPath(); + String compilerPath; if (pathToCompiler.isPresent()) { - return pathToCompiler.get(); + compilerPath = pathToCompiler.get(); + } else { + compilerPath = getBuiltInCompilerPath(); + } + File file = new File(compilerPath); + if (!file.canExecute()) { + if(!file.setExecutable(true)) { + throw new IllegalStateException("Compiler " + pathToCompiler + " is not executabel and cannot be set to be."); + }; } - return getBuiltInCompilerPath(); + return compilerPath; } protected String getBuiltInCompilerPath() { @@ -142,9 +135,6 @@ protected String getBuiltInCompilerPath() { URL url = FileLocator.find(bundle, getPath(), null); try { URL fileURL = FileLocator.toFileURL(url); - File file = new File(fileURL.toURI()); - if (!file.canExecute()) - file.setExecutable(true); return fileURL.getFile(); } catch (Exception e) { throw new IllegalStateException(e); diff --git a/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/builder/processor/OutputParser.java b/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/builder/processor/OutputParser.java index 1b0f81ae..dc674a58 100644 --- a/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/builder/processor/OutputParser.java +++ b/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/builder/processor/OutputParser.java @@ -15,6 +15,7 @@ package com.yakindu.solidity.solc.builder.processor; import java.io.BufferedReader; +import java.io.File; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.reflect.Type; @@ -24,8 +25,6 @@ import java.util.Optional; import java.util.Set; -import org.eclipse.core.resources.IResource; - import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; @@ -143,7 +142,7 @@ private String readStringMember(JsonObject object, String key) { return (element == null) ? null : element.getAsString(); } - public Optional parse(final InputStream stream, final Set filesToCompile) { + public Optional parse(final InputStream stream, final Set filesToCompile) { try (final InputStreamReader output = new InputStreamReader(stream, "UTF-8"); final BufferedReader out = new BufferedReader(output);) { CompilerOutput compilerOutput = gson.create().fromJson(output, CompilerOutput.class); diff --git a/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/output/FileOutputProcessor.java b/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/output/FileOutputProcessor.java index 4259038f..844d7e3c 100644 --- a/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/output/FileOutputProcessor.java +++ b/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/output/FileOutputProcessor.java @@ -24,9 +24,6 @@ import javax.inject.Inject; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IResource; - import com.google.gson.GsonBuilder; import com.yakindu.solidity.solc.preferences.ICompilerPreferences; import com.yakindu.solidity.solc.result.Abi; @@ -45,8 +42,7 @@ public class FileOutputProcessor { private ICompilerPreferences prefs; private final GsonBuilder gsonBuilder = new GsonBuilder().setPrettyPrinting(); - public void writeOutputFiles(CompilerOutput compilerOutput, Set filesToCompile) { - + public void writeOutputFiles(CompilerOutput compilerOutput, Set filesToCompile) { for (Entry> entry : compilerOutput.getContracts().entrySet()) { String outputFileName = getOutputFileName(findFileForName(filesToCompile, entry.getKey())); for (CompiledContract contract : entry.getValue().values()) { @@ -62,9 +58,8 @@ public void writeOutputFiles(CompilerOutput compilerOutput, Set files } } - private String getOutputFileName(IFile file) { - String plainFileName = file.getName().replaceAll(".sol", ""); - return file.getProject().getLocation().append(prefs.getCompilerOutputPath()).append(plainFileName).toOSString(); + private String getOutputFileName(File file) { + return file.getPath().replaceAll(".sol", ""); } private void writeASMFile(String outputFileName, String assembly) { @@ -109,9 +104,9 @@ private void writeFile(String outputFileName, String content) { } } - private IFile findFileForName(Set filesToCompile, String fileName) { - IFile errorFile = filesToCompile.stream().filter(file -> file.getName().equals(fileName)) - .map(file -> (IFile) file).findFirst().orElse(null); + private File findFileForName(Set filesToCompile, String fileName) { + File errorFile = filesToCompile.stream().filter(file -> file.getName().equals(fileName)) + .map(file -> (File) file).findFirst().orElse(null); return errorFile; } } diff --git a/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/output/OutputParser.java b/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/output/OutputParser.java index 0d533ccb..fc5f7546 100644 --- a/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/output/OutputParser.java +++ b/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/output/OutputParser.java @@ -15,17 +15,18 @@ package com.yakindu.solidity.solc.output; import java.io.BufferedReader; +import java.io.File; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.StringReader; import java.lang.reflect.Type; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Optional; import java.util.Set; -import org.eclipse.core.resources.IResource; - import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; @@ -143,7 +144,7 @@ private String readStringMember(JsonObject object, String key) { return (element == null) ? null : element.getAsString(); } - public Optional parse(final InputStream stream, final Set filesToCompile) { + public Optional parse(final InputStream stream, final Set filesToCompile) { try (final InputStreamReader output = new InputStreamReader(stream, "UTF-8"); final BufferedReader out = new BufferedReader(output);) { CompilerOutput compilerOutput = gson.create().fromJson(output, CompilerOutput.class); diff --git a/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/output/SolidityIssueCreator.java b/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/output/SolidityIssueCreator.java index fbca0173..35da6cb5 100644 --- a/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/output/SolidityIssueCreator.java +++ b/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/output/SolidityIssueCreator.java @@ -1,7 +1,6 @@ package com.yakindu.solidity.solc.output; -import java.io.BufferedReader; -import java.io.InputStreamReader; +import java.io.File; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -9,9 +8,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.eclipse.core.internal.utils.FileUtil; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IResource; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; @@ -21,13 +17,12 @@ import org.eclipse.xtext.validation.ValidationMessageAcceptor; import org.yakindu.base.types.Package; -import com.google.common.collect.Maps; import com.google.inject.Inject; import com.yakindu.solidity.solc.result.CompileError; import com.yakindu.solidity.solc.result.CompiledContract; import com.yakindu.solidity.solc.result.GasEstimates; +import com.yakindu.solidity.solc.result.SourceLocation; -@SuppressWarnings("restriction") public class SolidityIssueCreator { private static final String INFO = "info"; @@ -39,7 +34,7 @@ public class SolidityIssueCreator { @Inject private EObjectAtOffsetHelper offsetHelper; - public void createErrors(final List errors, final Set filesToCompile, + public void createErrors(final List errors, final Set filesToCompile, EObject currentObject, ValidationMessageAcceptor acceptor) { if (errors == null) { return; @@ -49,7 +44,7 @@ public void createErrors(final List errors, final Set f } } - public void createInfos(Map> contracts, Set filesToCompile, + public void createInfos(Map> contracts, Set filesToCompile, EObject currentObject, ValidationMessageAcceptor acceptor) { if (contracts == null) { return; @@ -59,11 +54,16 @@ public void createInfos(Map> contracts, Se findFileForName(filesToCompile, entry.getKey()), currentObject, acceptor))); } - protected void createSolcIssue(CompileError error, Set filesToCompile, EObject currentObject, + protected void createSolcIssue(CompileError error, Set filesToCompile, EObject currentObject, ValidationMessageAcceptor acceptor) { - String fileName = error.getSourceLocation().getFile(); - IFile errorFile = findFileForName(filesToCompile, fileName); - int offset = error.getSourceLocation().getStart(); + SourceLocation sourceLocation = error.getSourceLocation(); + if(sourceLocation == null) { + return; + } + + String fileName = sourceLocation.getFile(); + File errorFile = findFileForName(filesToCompile, fileName); + int offset = sourceLocation.getStart(); String message = error.getMessage(); EObject element = getEObject(errorFile, offset, currentObject); String severity = error.getSeverity(); @@ -74,7 +74,7 @@ protected void createSolcIssue(CompileError error, Set filesToCompile } } - protected void createInfoIssue(CompiledContract contract, IFile file, EObject currentObject, + protected void createInfoIssue(CompiledContract contract, File file, EObject currentObject, ValidationMessageAcceptor acceptor) { if (contract.getEvm() == null || contract.getEvm().getGasEstimates() == null) { return; @@ -85,9 +85,9 @@ protected void createInfoIssue(CompiledContract contract, IFile file, EObject cu acceptor.acceptInfo(message, element.eContainer(), 0, 0, createErrorCodeFromMessage(INFO, message)); } - protected IFile findFileForName(Set filesToCompile, String fileName) { - IFile errorFile = filesToCompile.stream().filter(file -> file.getName().equals(fileName)) - .map(file -> (IFile) file).findFirst().orElse((IFile) filesToCompile.stream().findFirst().orElse(null)); + protected File findFileForName(Set filesToCompile, String fileName) { + File errorFile = filesToCompile.stream().filter(file -> file.getName().equals(fileName)) + .map(file -> (File) file).findFirst().orElse((File) filesToCompile.stream().findFirst().orElse(null)); return errorFile; } @@ -143,7 +143,7 @@ protected int calculateIssueLength(String errorMessage, Pattern pattern) { return 0; } - protected EObject getEObject(IFile errorFile, int offset, EObject currentObject) { + protected EObject getEObject(File errorFile, int offset, EObject currentObject) { Resource resource = currentObject.eResource(); if (offset == 0) { EList resourceContent = resource.getContents(); @@ -184,24 +184,6 @@ protected void printMethodEstimations(Map map, StringBuilder bui } } - protected Map getFileContent(IFile file) { - String fileEnding = FileUtil.getLineSeparator(file); - Map content = Maps.newHashMap(); - try (BufferedReader reader = new BufferedReader( - new InputStreamReader(file.getContents(true), file.getCharset()));) { - String line = reader.readLine(); - int lastLineNumber = 1; - while (line != null) { - content.put(lastLineNumber, line + fileEnding); - line = reader.readLine(); - lastLineNumber++; - } - } catch (Exception e) { - e.printStackTrace(); - } - return content; - } - protected String createErrorCodeFromMessage(String severity, String message) { switch (severity) { case ERROR: diff --git a/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/parameter/Source.java b/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/parameter/Source.java index e63b34cb..97d8f2f7 100644 --- a/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/parameter/Source.java +++ b/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/parameter/Source.java @@ -15,31 +15,26 @@ package com.yakindu.solidity.solc.parameter; import java.io.BufferedReader; -import java.io.InputStreamReader; +import java.io.File; +import java.io.FileReader; import java.util.List; -import org.eclipse.core.internal.utils.FileUtil; -import org.eclipse.core.resources.IFile; - /** * * @author Florian Antony - Initial contribution and API * */ -@SuppressWarnings("restriction") public class Source { String keccak256; String content = ""; List urls; - public Source(IFile file) { - String seperator = FileUtil.getLineSeparator(file); - try (BufferedReader reader = new BufferedReader( - new InputStreamReader(file.getContents(true), file.getCharset()));) { + public Source(File file) { + try (BufferedReader reader = new BufferedReader(new FileReader(file))) { String line = reader.readLine(); while (line != null) { - content += line + seperator; + content += line; line = reader.readLine(); } } catch (Exception e) { diff --git a/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/preferences/ICompilerPreferences.java b/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/preferences/ICompilerPreferences.java index 05b389d9..09a6f369 100644 --- a/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/preferences/ICompilerPreferences.java +++ b/plugins/com.yakindu.solidity.solc/src/com/yakindu/solidity/solc/preferences/ICompilerPreferences.java @@ -46,6 +46,8 @@ public interface ICompilerPreferences { Optional getCompilerPath(); boolean isCompilerEnabled(); + + IEclipsePreferences getPreferences(); /** * diff --git a/plugins/com.yakindu.solidity.tests/.classpath b/plugins/com.yakindu.solidity.tests/.classpath index 43b98628..2f5ffb21 100644 --- a/plugins/com.yakindu.solidity.tests/.classpath +++ b/plugins/com.yakindu.solidity.tests/.classpath @@ -3,5 +3,6 @@ + diff --git a/plugins/com.yakindu.solidity.tests/META-INF/MANIFEST.MF b/plugins/com.yakindu.solidity.tests/META-INF/MANIFEST.MF index 34270dee..b387a3d4 100644 --- a/plugins/com.yakindu.solidity.tests/META-INF/MANIFEST.MF +++ b/plugins/com.yakindu.solidity.tests/META-INF/MANIFEST.MF @@ -8,7 +8,13 @@ Bundle-ActivationPolicy: lazy Require-Bundle: com.yakindu.solidity, org.eclipse.xtext.testing, org.eclipse.jdt.junit.runtime, - org.junit + org.junit, + org.eclipse.xtext.ui.testing, + com.yakindu.solidity.ide, + com.yakindu.solidity.ui, + org.yakindu.base.expressions.ui, + org.eclipse.xtext.xbase.lib, + org.eclipse.xtext.ui.testing Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Export-Package: com.yakindu.solidity.tests;x-internal=true Import-Package: org.hamcrest.core;version="1.3.0", diff --git a/plugins/com.yakindu.solidity.tests/pom.xml b/plugins/com.yakindu.solidity.tests/pom.xml index 2e226ccf..59d16c99 100644 --- a/plugins/com.yakindu.solidity.tests/pom.xml +++ b/plugins/com.yakindu.solidity.tests/pom.xml @@ -1,4 +1,5 @@ - 4.0.0 @@ -12,6 +13,22 @@ + + org.eclipse.tycho + target-platform-configuration + ${tycho-version} + + + + + eclipse-feature + com.yakindu.solidity.solc.feature + 0.0.0 + + + + + org.eclipse.tycho tycho-surefire-plugin @@ -19,14 +36,15 @@ **/AllTests.class - + false false ${testFailureIgnore} ${test.vmargs} - - JavaSE-11 + + JavaSE-11 diff --git a/plugins/com.yakindu.solidity.tests/src/com/yakindu/solidity/tests/SolidityInjectorProvider.java b/plugins/com.yakindu.solidity.tests/src/com/yakindu/solidity/tests/SolidityInjectorProvider.java index 95aa7376..8c6c7b0c 100644 --- a/plugins/com.yakindu.solidity.tests/src/com/yakindu/solidity/tests/SolidityInjectorProvider.java +++ b/plugins/com.yakindu.solidity.tests/src/com/yakindu/solidity/tests/SolidityInjectorProvider.java @@ -3,15 +3,15 @@ */ package com.yakindu.solidity.tests; -import com.google.inject.Guice; -import com.google.inject.Injector; -import com.yakindu.solidity.SolidityRuntimeModule; -import com.yakindu.solidity.SolidityStandaloneSetup; import org.eclipse.xtext.testing.GlobalRegistries; import org.eclipse.xtext.testing.GlobalRegistries.GlobalStateMemento; import org.eclipse.xtext.testing.IInjectorProvider; import org.eclipse.xtext.testing.IRegistryConfigurator; +import com.google.inject.Injector; +import com.yakindu.solidity.SolidityStandaloneSetup; +import com.yakindu.solidity.ui.internal.SolidityActivator; + public class SolidityInjectorProvider implements IInjectorProvider, IRegistryConfigurator { protected GlobalStateMemento stateBeforeInjectorCreation; @@ -36,23 +36,11 @@ protected Injector internalCreateInjector() { return new SolidityStandaloneSetup() { @Override public Injector createInjector() { - return Guice.createInjector(createRuntimeModule()); + return SolidityActivator.getInstance().getInjector("com.yakindu.solidity.Solidity"); } }.createInjectorAndDoEMFRegistration(); } - protected SolidityRuntimeModule createRuntimeModule() { - // make it work also with Maven/Tycho and OSGI - // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=493672 - return new SolidityRuntimeModule() { - @Override - public ClassLoader bindClassLoaderToInstance() { - return SolidityInjectorProvider.class - .getClassLoader(); - } - }; - } - @Override public void restoreRegistry() { stateBeforeInjectorCreation.restoreGlobalState(); diff --git a/plugins/com.yakindu.solidity.ui.tests/.classpath b/plugins/com.yakindu.solidity.ui.tests/.classpath new file mode 100644 index 00000000..4a3597ed --- /dev/null +++ b/plugins/com.yakindu.solidity.ui.tests/.classpath @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/plugins/com.yakindu.solidity.ui.tests/.project b/plugins/com.yakindu.solidity.ui.tests/.project new file mode 100644 index 00000000..9e89ec3f --- /dev/null +++ b/plugins/com.yakindu.solidity.ui.tests/.project @@ -0,0 +1,34 @@ + + + com.yakindu.solidity.ui.tests + + + + + + org.eclipse.xtext.ui.shared.xtextBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + org.eclipse.xtext.ui.shared.xtextNature + + diff --git a/plugins/com.yakindu.solidity.ui.tests/.settings/org.eclipse.core.resources.prefs b/plugins/com.yakindu.solidity.ui.tests/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 00000000..99f26c02 --- /dev/null +++ b/plugins/com.yakindu.solidity.ui.tests/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/plugins/com.yakindu.solidity.ui.tests/.settings/org.eclipse.jdt.core.prefs b/plugins/com.yakindu.solidity.ui.tests/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..0c68a61d --- /dev/null +++ b/plugins/com.yakindu.solidity.ui.tests/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/plugins/com.yakindu.solidity.ui.tests/META-INF/MANIFEST.MF b/plugins/com.yakindu.solidity.ui.tests/META-INF/MANIFEST.MF new file mode 100644 index 00000000..02ff6283 --- /dev/null +++ b/plugins/com.yakindu.solidity.ui.tests/META-INF/MANIFEST.MF @@ -0,0 +1,23 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Tests +Bundle-SymbolicName: com.yakindu.solidity.ui.tests +Bundle-Version: 0.7.3.qualifier +Bundle-Vendor: YAKINDU +Automatic-Module-Name: com.yakindu.solidity.ui.tests +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Export-Package: com.yakindu.solidity.ui.tests;x-internal=true +Require-Bundle: + com.google.gson, + org.eclipse.xtext.junit4, + org.eclipse.core.runtime, + org.eclipse.ui.workbench, + org.eclipse.xtend.lib, + org.eclipse.xtext.xbase.lib, + org.eclipse.xtext.testing, + com.yakindu.solidity.ui, + org.eclipse.xtext.ui.testing, + com.yakindu.solidity, + org.eclipse.jdt.junit.runtime, + org.junit, + com.yakindu.solidity.solc diff --git a/plugins/com.yakindu.solidity.ui.tests/build.properties b/plugins/com.yakindu.solidity.ui.tests/build.properties new file mode 100644 index 00000000..a6835df7 --- /dev/null +++ b/plugins/com.yakindu.solidity.ui.tests/build.properties @@ -0,0 +1,6 @@ +source.. = src/,\ + src-gen/,\ + xtend-gen/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/plugins/com.yakindu.solidity.ui.tests/pom.xml b/plugins/com.yakindu.solidity.ui.tests/pom.xml new file mode 100644 index 00000000..fcac2e23 --- /dev/null +++ b/plugins/com.yakindu.solidity.ui.tests/pom.xml @@ -0,0 +1,114 @@ + + 4.0.0 + + com.yakindu.solidity + com.yakindu.solidity.releng + 0.7.3-SNAPSHOT + ../../releng/com.yakindu.solidity.releng/pom.xml + + com.yakindu.solidity.ui.tests + eclipse-test-plugin + + + + macosx + + + mac + + + + -Xmx1024m -Xss2m -XX:MaxPermSize=256m + -XstartOnFirstThread + + + + other-os + + + !mac + + + + -Xmx1024m -Xss2m -XX:MaxPermSize=256m + + + + + + + + org.eclipse.tycho + tycho-surefire-plugin + ${tycho-version} + + + **/AllTests.class + + true + true + ${testFailureIgnore} + ${test.vmargs} + + + + eclipse-feature + com.yakindu.solidity.solc.feature + 0.0.0 + + + + + + + org.eclipse.tycho + target-platform-configuration + ${tycho-version} + + + + + eclipse-feature + com.yakindu.solidity.solc.feature + 0.0.0 + + + + + + + maven-clean-plugin + + + + xtend-gen + + ** + + + .gitignore + + + + + + + org.eclipse.xtend + xtend-maven-plugin + + + + compile + + + + + ${project.build.sourceEncoding} + xtend-gen + + + + + \ No newline at end of file diff --git a/plugins/com.yakindu.solidity.ui.tests/src/com/yakindu/solidity/ui/tests/AllTests.java b/plugins/com.yakindu.solidity.ui.tests/src/com/yakindu/solidity/ui/tests/AllTests.java new file mode 100644 index 00000000..6518e07f --- /dev/null +++ b/plugins/com.yakindu.solidity.ui.tests/src/com/yakindu/solidity/ui/tests/AllTests.java @@ -0,0 +1,12 @@ +package com.yakindu.solidity.ui.tests; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + + +@RunWith(Suite.class) +@SuiteClasses({ SolidityQuickfixTests.class }) +public class AllTests { + +} diff --git a/plugins/com.yakindu.solidity.ui.tests/src/com/yakindu/solidity/ui/tests/SolidityQuickfixTests.xtend b/plugins/com.yakindu.solidity.ui.tests/src/com/yakindu/solidity/ui/tests/SolidityQuickfixTests.xtend new file mode 100644 index 00000000..f6838542 --- /dev/null +++ b/plugins/com.yakindu.solidity.ui.tests/src/com/yakindu/solidity/ui/tests/SolidityQuickfixTests.xtend @@ -0,0 +1,934 @@ +/** + * Copyright (c) 2019 committers of YAKINDU and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andreas Muelder - Itemis AG - initial API and implementation + * Karsten Thoms - Itemis AG - initial API and implementation + * Florian Antony - Itemis AG - initial API and implementation + * committers of YAKINDU + * + */ +package com.yakindu.solidity.ui.tests + +import com.google.inject.Inject +import com.google.inject.name.Named +import com.yakindu.solidity.SolidityVersion +import org.eclipse.xtext.testing.InjectWith +import org.eclipse.xtext.testing.XtextRunner +import org.eclipse.xtext.ui.testing.AbstractQuickfixTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +import static com.yakindu.solidity.validation.IssueCodes.* + +/** + * This class tests the quickfixes for the solidity ide + * @author Jonathan Thoene - Initial contribution + */ + +@RunWith(XtextRunner) +@InjectWith(SolidityUiInjectorProvider) +class SolidityQuickfixTests extends AbstractQuickfixTest { + + @Inject @Named(SolidityVersion.SOLIDITY_VERSION) String solcVersion + + @Before + def void setup() { + } + + @Test + def void testFixForMissingPayableDeclaration() { + var modelToFix = ''' + pragma solidity ^0.5.9; + + contract MyContract { + address creator; + + constructor() public{ + creator = msg.sender; + } + + // TODO Add functions + + function kill() public { + if (msg.sender == creator) { + selfdestruct(creator); + } + } + } + ''' + + var expectedResult = ''' + pragma solidity ^0.5.9; + + contract MyContract { + address payable creator; + + constructor() public{ + creator = msg.sender; + } + + // TODO Add functions + + function kill() public { + if (msg.sender == creator) { + selfdestruct(creator); + } + } + } + ''' + testQuickfixesOn( + modelToFix, + ERROR_INVALID_IMPLICID_CONVERSION_TO_ADDRESS_PAYABLE, + new Quickfix("Add payable to declaration", "Add payable to declaration", expectedResult) + ) + } + + @Test + def void testFixForMissingSolidityPragma() { + var modelToFix = ''' + contract MyContract { + constructor() public{} + } + ''' + + var expectedResult = ''' + pragma solidity «solcVersion» ; contract MyContract { + constructor() public{} + } + + + ''' + testQuickfixesOn( + modelToFix, + WARNING_FILE_NO_PRAGMA_SOLIDITY, + new Quickfix("Add default solidity pragma", '''Add solidity pragma «solcVersion».''', expectedResult) + ) + } + + @Test + def void testFixForViewModifierInsteadOfPureModifier() { + var modelToFix1 = ''' + pragma solidity ^0.5.4; + + contract Contract { + function f() public view returns (uint) { + return 0; + } + } + ''' + + var expectedResult1 = ''' + pragma solidity ^0.5.4; + + contract Contract { + function f() public pure returns (uint) { + return 0; + } + } + ''' + testQuickfixesOn( + modelToFix1, + WARNING_FUNCTION_STATE_MUTABILITY_PURE, + new Quickfix('Use "pure" instead.', 'Use "pure" instead.', expectedResult1) + ) + } + + @Test + def void testFixForUnusedParameter() { + var modelToFix = ''' + pragma solidity ^0.5.9; + + contract Test { + function test(address payable create) pure public returns (uint){ + return 0; + } + } + ''' + + var expectedResult = ''' + pragma solidity ^0.5.9; + + contract Test { + function test() pure public returns (uint){ + return 0; + } + } + ''' + testQuickfixesOn( + modelToFix, + WARNING_FUNCTION_UNUSED_PARAMETER, + new Quickfix('Removed unused parameter declaration', 'Removed unused parameter declaration.', + expectedResult) + ) + } + + @Test + def void testFixForRemovedConstantModifier() { + var modelToFix = ''' + pragma solidity ^0.5.9; + + contract Test { + function test() constant public returns (uint){ + return 0; + } + } + ''' + + var expectedResultQuickfix1 = ''' + pragma solidity ^0.5.9; + + contract Test { + function test() pure public returns (uint){ + return 0; + } + } + ''' + + var expectedResultQuickfix2 = ''' + pragma solidity ^0.5.9; + + contract Test { + function test() view public returns (uint){ + return 0; + } + } + ''' + testQuickfixesOn( + modelToFix, + ERROR_CONSTANT_MODIFIER_WAS_REMOVED, + new Quickfix('Use "pure" instead.', 'Use "pure" instead.', expectedResultQuickfix1), + new Quickfix('Use "view" instead.', 'Use "view" instead.', expectedResultQuickfix2) + ) + } + + @Test + def void testFixForMethodWithSameNameAsContract() { + var modelToFix = ''' + pragma solidity ^0.5.9; + + contract Test { + function Test() public { + } + } + ''' + + var expectedResult = ''' + pragma solidity ^0.5.9; + + contract Test { + + constructor () public { + + } + } + + + ''' + testQuickfixesOn( + modelToFix, + ERROR_FUNCTION_NAME_EQUALS_CONTRACT_NAME_DISALLOWED, + new Quickfix('Use constructor keyword instead', 'contructor keyword', expectedResult) + ) + } + + @Test + def void testFixForDeprecatedSuicideFunction() { + var modelToFix = ''' + pragma solidity ^0.5.9; + + contract Test { + address payable creator; + function kill() public + { + if (msg.sender == creator) + suicide(creator); + } + } + ''' + + var expectedResult = ''' + pragma solidity ^0.5.9; + + contract Test { + address payable creator; + function kill() public + { + if (msg.sender == creator) + selfdestruct(creator); + } + } + ''' + testQuickfixesOn( + modelToFix, + ERROR_DEPRECATED_SUICIDE, + new Quickfix('Replace with selfdestruct', 'selfdestruct', expectedResult) + ) + } + + @Test + def void testFixForUnusedLocalVariable() { + var modelToFix = ''' + pragma solidity ^0.5.9; + + contract Test { + function test() pure internal { + bytes memory one = abi.encode("test"); + } + } + ''' + + var expectedResult = ''' + pragma solidity ^0.5.9; + + contract Test { + function test() pure internal { } + } + ''' + testQuickfixesOn( + modelToFix, + WARNING_LOCAL_VARIABLE_UNUSED, + new Quickfix('Remove unused local variable', 'remove unused local variable', expectedResult) + ) + } + + @Test + def void testFixForMissingViewModifier() { + var modelToFix = ''' + pragma solidity ^0.5.9; + + contract Test { + constructor () public { + } + string signature =""; + + function test() internal returns (string storage){ + return signature; + } + } + ''' + + var expectedResult = ''' + pragma solidity ^0.5.9; + + contract Test { + constructor () public { + } + string signature =""; + + function test() internal view returns (string storage){ + return signature; + } + } + ''' + testQuickfixesOn( + modelToFix, + WARNING_FUNCTION_STATE_MUTABILITY_VIEW, + new Quickfix('Add \'view\' modifier', 'view function', expectedResult) + ) + } + + @Test + def void testFixForMissingFunctionVisibility() { + var modelToFix = ''' + pragma solidity ^0.5.9; + + contract Test { + string signature =""; + + function test() returns (string memory){ + return signature; + } + } + ''' + + var expectedResultPublicModifier = ''' + pragma solidity ^0.5.9; + + contract Test { + string signature =""; + + function test() public returns (string memory){ + return signature; + } + } + ''' + + var expectedResultPrivateModifier = ''' + pragma solidity ^0.5.9; + + contract Test { + string signature =""; + + function test() private returns (string memory){ + return signature; + } + } + ''' + + var expectedResultInternalModifier = ''' + pragma solidity ^0.5.9; + + contract Test { + string signature =""; + + function test() internal returns (string memory){ + return signature; + } + } + ''' + + var expectedResultExternalModifier = ''' + pragma solidity ^0.5.9; + + contract Test { + string signature =""; + + function test() external returns (string memory){ + return signature; + } + } + ''' + testQuickfixesOn( + modelToFix, + ERROR_NO_VISIBILITY_SPECIFIED, + new Quickfix('Make this function \'public\'', 'Public function.', expectedResultPublicModifier), + new Quickfix('Make this function private', 'Private function.', expectedResultPrivateModifier), + new Quickfix('Make this function \'internal\'', 'Internal function.', expectedResultInternalModifier), + new Quickfix('Make this function \'external\'', 'External function.', expectedResultExternalModifier) + ) + } + + @Test + def void testFixForMissingMemoryKeyword() { + var modelToFix = ''' + pragma solidity ^0.5.9; + + contract Test { + string signature =""; + + function test() external view returns (string){ + return signature; + } + } + ''' + + var expectedResult = ''' + pragma solidity ^0.5.9; + + contract Test { + string signature =""; + + function test() external view returns (string memory){ + return signature; + } + } + ''' + testQuickfixesOn( + modelToFix, + ERROR_DATA_LOCATION_MUST_BE_MEMORY_FOR_RETURN_PARAMETER, + new Quickfix('Add \'memory\' modifier.', 'Data location must be "memory" here. Add \'memory\' modifier.', + expectedResult) + ) + } + + @Test + def void testFixForMissingCalldataKeyword() { + var modelToFix = ''' + pragma solidity ^0.5.9; + + contract Test { + string signature =""; + + function test(string other) external view returns (string memory){ + return signature; + } + } + ''' + + var expectedResult = ''' + pragma solidity ^0.5.9; + + contract Test { + string signature =""; + + function test(string calldata other) external view returns (string memory){ + return signature; + } + } + ''' + testQuickfixesOn( + modelToFix, + ERROR_DATA_LOCATION_MUST_BE_CALLDATA_FOR_EXTERNAL_PARAMETER, + new Quickfix('Add \'calldata\' modifier.', + 'Data location must be \"calldata\" for parameter in external function.', expectedResult) + ) + } + + @Test + def void testFixForDeprecatedSha3Function() { + var modelToFix = ''' + pragma solidity ^0.5.9; + + contract Test { + function getSHA3Hash(bytes memory input) public returns (bytes32 hashedOutput) + { + hashedOutput = sha3(input); + } + } + ''' + + var expectedResult = ''' + pragma solidity ^0.5.9; + + contract Test { + function getSHA3Hash(bytes memory input) public returns (bytes32 hashedOutput) + { + hashedOutput = keccak256(input); + } + } + ''' + testQuickfixesOn( + modelToFix, + ERROR_DEPRECATED_SHA3, + new Quickfix('Replace Sha3 with keccak256', 'keccak256(...) returns (bytes32).', expectedResult) + ) + } + +// TODO: Quickfix for this does not work and needs to be fixed first (method 'replaceVarKeyword'). See issue #299 +// +// @Test +// def void testFixForDisallowedKeywordVar() { +// var modelToFix = ''' +// pragma solidity ^0.5.9; +// +// contract Test { +// function return0() pure public returns (uint8) +// { +// var x = 0; +// return x; +// } +// } +// ''' +// +// var expectedResult = ''' +// pragma solidity ^0.5.9; +// +// contract Test { +// function return0() pure public returns (uint8) +// { +// uint8 x = 0; +// return x; +// } +// } +// ''' +// testQuickfixesOn( +// modelToFix, +// ERROR_VAR_KEYWORD_DISALLOWED, +// new Quickfix('Inferr type information', 'Inferr type information', expectedResult) +// ) +// } + @Test + def void testFixForDeprecatedThrowExpression() { + var modelToFix = ''' + pragma solidity ^0.5.9; + + contract Test { + function test() pure public + { + if (true) { throw; } + } + } + ''' + + var expectedResultForRevert = ''' + pragma solidity ^0.5.9; + + contract Test { + function test() pure public + { + if (true) { revert ( "Something bad happened" ) ; } + } + } + ''' + + var expectedResultForAssert = ''' + pragma solidity ^0.5.9; + + contract Test { + function test() pure public + { assert ( true ) ; + } + } + ''' + + var expectedResultForRequire = ''' + pragma solidity ^0.5.9; + + contract Test { + function test() pure public + { require ( true , "Preconditions are not satisfied" ) ; + } + } + ''' + testQuickfixesOn( + modelToFix, + ERROR_THROW_KEYWORD_DISALLOWED, + new Quickfix('Replace with revert', 'revert(\'Something bad happened\').', expectedResultForRevert), + new Quickfix('Replace with assert', 'assert(condition)', expectedResultForAssert), + new Quickfix('Replace with require', 'require(condition, \'Precondition are not met\')', + expectedResultForRequire) + ) + } + + @Test + def void testFixForDeprecatedYearsUnit() { + var modelToFix = ''' + pragma solidity ^0.5.9; + + contract Test { + + function test() pure public returns (uint256) { + return 5 years; + } + } + ''' + + var expectedResult = ''' + pragma solidity ^0.5.9; + + contract Test { + + function test() pure public returns (uint256) { + return 1825 days; + } + } + ''' + + testQuickfixesOn( + modelToFix, + ERROR_YEARS_IS_DISALLOWED, + new Quickfix('Change years unit denomination to days', 'Change years unit denomination to days', + expectedResult) + ) + } + + @Test + def void testFixForWrongStateMutability() { + var modelToFix = ''' + pragma solidity ^0.5.9; + + contract Test { + + function test() pure public returns (uint8) { + uint8 payable x = 15; + return x; + } + } + ''' + + var expectedResult = ''' + pragma solidity ^0.5.9; + + contract Test { + + function test() pure public returns (uint8) { + uint8 x = 15; + return x; + } + } + ''' + + testQuickfixesOn( + modelToFix, + ERROR_STATE_MUTABILITY_ONLY_ALLOWED_FOR_ADDRESS, + new Quickfix('Remove payable declaration', 'Remove payable declaration', expectedResult) + ) + } + + @Test + def void testFixForFunctionNotDeclaredAsPayable() { + var modelToFix = ''' + pragma solidity ^0.5.9; + + contract Test { + uint amount =0; + function payme() view public { + amount += msg.value; + } + } + ''' + + var expectedResultChangeToPayable = ''' + pragma solidity ^0.5.9; + + contract Test { + uint amount =0; + function payme() payable public { + amount += msg.value; + } + } + ''' + + var expectedResultRemoveView = ''' + pragma solidity ^0.5.9; + + contract Test { + uint amount =0; + function payme() public { + amount += msg.value; + } + } + ''' + + testQuickfixesOn( + modelToFix, + ERROR_FUNCTION_DECLARED_AS_VIEW_BUT_MUST_BE_PAYABLE_OR_NON_PAYABLE, + new Quickfix('Change to "payable".', 'Change to "payable".', expectedResultChangeToPayable), + new Quickfix('Remove \"view\" and make function non-payable.', + 'Remove \"view\" and make function non-payable.', expectedResultRemoveView) + ) + } + + @Test + def void testFixForInterfaceFunctionWithModifier() { + var modelToFix = ''' + pragma solidity ^0.5.9; + + interface TestInterface { + + modifier testModifier() { + _; + } + function test() testModifier external; + } + ''' + + var expectedResult = ''' + pragma solidity ^0.5.9; + + interface TestInterface { + + modifier testModifier() { + _; + } + function test() external; + } + ''' + + testQuickfixesOn( + modelToFix, + ERROR_INTERFACE_FUNCTIONS_CAN_NOT_HAVE_MODIFIERS, + new Quickfix('Remove all disallowed modifiers.', 'Remove all disallowed modifiers.', expectedResult) + ) + } + + @Test + def void testFixForMissingParameterDataLocationSpecification() { + var modelToFix = ''' + pragma solidity ^0.5.9; + + contract Test { + function test(bytes data) pure internal returns (uint transactionId) + { + return 0; + } + } + ''' + + var expectedResultMemory = ''' + pragma solidity ^0.5.9; + + contract Test { + function test(bytes memory data) pure internal returns (uint transactionId) + { + return 0; + } + } + ''' + + var expectedResultStorage = ''' + pragma solidity ^0.5.9; + + contract Test { + function test(bytes storage data) pure internal returns (uint transactionId) + { + return 0; + } + } + ''' + + testQuickfixesOn( + modelToFix, + ERROR_DATA_LOCATION_MUST_BE_STORAGE_OR_MEMORY_FOR_PARAMETER, + new Quickfix('Add \'memory\' modifier.', 'Data location must be "memory" here. Add \'memory\' modifier.', + expectedResultMemory), + new Quickfix('Add \'storage\' modifier.', 'Data location must be "storage" here. Add \'storage\' modifier.', + expectedResultStorage) + ) + } + + @Test + def void testFixForMissingVariableDataLocationSpecification() { + var modelToFix = ''' + pragma solidity ^0.5.9; + + contract Test { + function test() pure internal returns (uint transactionId) + { + bytes data; + return 0; + } + } + ''' + + var expectedResultMemory = ''' + pragma solidity ^0.5.9; + + contract Test { + function test() pure internal returns (uint transactionId) + { + bytes memory data; + return 0; + } + } + ''' + + var expectedResultStorage = ''' + pragma solidity ^0.5.9; + + contract Test { + function test() pure internal returns (uint transactionId) + { + bytes storage data; + return 0; + } + } + ''' + + testQuickfixesOn( + modelToFix, + ERROR_DATA_LOCATION_MUST_BE_SPECIFIED_FOR_VARIABLE, + new Quickfix('Add \'memory\' modifier.', 'Add \'memory\' modifier.', + expectedResultMemory), + new Quickfix('Add \'storage\' modifier.', 'Add \'storage\' modifier.', + expectedResultStorage) + ) + } + + @Test + def void testFixForMissingReturnParameterDataLocationSpecification() { + var modelToFix = ''' + pragma solidity ^0.5.9; + + contract Test { + function test(bytes memory data) pure internal returns (bytes transactionId) + { + return data; + } + } + ''' + + var expectedResultMemory = ''' + pragma solidity ^0.5.9; + + contract Test { + function test(bytes memory data) pure internal returns (bytes memory transactionId) + { + return data; + } + } + ''' + + var expectedResultStorage = ''' + pragma solidity ^0.5.9; + + contract Test { + function test(bytes memory data) pure internal returns (bytes storage transactionId) + { + return data; + } + } + ''' + + testQuickfixesOn( + modelToFix, + ERROR_DATA_LOCATION_MUST_BE_MEMORY_OR_STORAGE_FOR_RETURN_PARAMETER, + new Quickfix('Add \'memory\' modifier.', 'Data location must be "memory" here. Add \'memory\' modifier.', + expectedResultMemory), + new Quickfix('Add \'storage\' modifier.', 'Data location must be "storage" here. Add \'storage\' modifier.', + expectedResultStorage) + ) + } + + @Test + def void testFixForMissingMemoryModifierForParameter() { + var modelToFix = ''' + pragma solidity ^0.5.9; + + contract Test { + string public name; + function setName(string newName) public { + name = newName; + + } + } + ''' + + var expectedResult = ''' + pragma solidity ^0.5.9; + + contract Test { + string public name; + function setName(string memory newName) public { + name = newName; + + } + } + ''' + + testQuickfixesOn( + modelToFix, + ERROR_DATA_LOCATION_MUST_BE_MEMORY_FOR_PARAMETER, + new Quickfix('Add \'memory\' modifier.', 'Data location must be "memory" here. Add \'memory\' modifier.', + expectedResult) + ) + } + + @Test + def void testFixForDeprecatedSendFunction() { + var modelToFix = ''' + pragma solidity ^0.5.9; + + contract Test { + string public name; + function setName(address payable _add) public payable{ + _add.send(msg.value); + } + } + ''' + + var expectedResult = ''' + pragma solidity ^0.5.9; + + contract Test { + string public name; + function setName(address payable _add) public payable{ + _add.transfer(msg.value); + } + } + ''' + + testQuickfixesOn( + modelToFix, + WARNING_USSAGE_OF_SEND, + new Quickfix('Replace send with transfer', 'address.send(amount); -> address.transfer(amount);', + expectedResult) + ) + } +} diff --git a/plugins/com.yakindu.solidity.ui/META-INF/MANIFEST.MF b/plugins/com.yakindu.solidity.ui/META-INF/MANIFEST.MF index 51659d59..c082c855 100644 --- a/plugins/com.yakindu.solidity.ui/META-INF/MANIFEST.MF +++ b/plugins/com.yakindu.solidity.ui/META-INF/MANIFEST.MF @@ -25,7 +25,8 @@ Require-Bundle: com.yakindu.solidity, com.yakindu.solidity.solc Import-Package: org.apache.log4j Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Export-Package: com.yakindu.solidity.ui.contentassist, +Export-Package: com.yakindu.solidity.ui, + com.yakindu.solidity.ui.contentassist, com.yakindu.solidity.ui.highlighting, com.yakindu.solidity.ui.internal, com.yakindu.solidity.ui.preferences, diff --git a/plugins/com.yakindu.solidity.ui/pom.xml b/plugins/com.yakindu.solidity.ui/pom.xml index fb826be1..bfc5d11e 100644 --- a/plugins/com.yakindu.solidity.ui/pom.xml +++ b/plugins/com.yakindu.solidity.ui/pom.xml @@ -1,7 +1,8 @@ + xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 4.0.0 com.yakindu.solidity @@ -12,8 +13,25 @@ com.yakindu.solidity.ui com.yakindu.solidity eclipse-plugin + + + org.eclipse.tycho + tycho-surefire-plugin + ${tycho-version} + + + + + eclipse-feature + com.yakindu.solidity.solc.feature + 0.0.0 + + + + + org.eclipse.xtend xtend-maven-plugin @@ -27,6 +45,6 @@ - - + + diff --git a/plugins/com.yakindu.solidity.ui/src/com/yakindu/solidity/ui/SolidityUiModule.xtend b/plugins/com.yakindu.solidity.ui/src/com/yakindu/solidity/ui/SolidityUiModule.xtend index 4c373a05..f6ce55e9 100644 --- a/plugins/com.yakindu.solidity.ui/src/com/yakindu/solidity/ui/SolidityUiModule.xtend +++ b/plugins/com.yakindu.solidity.ui/src/com/yakindu/solidity/ui/SolidityUiModule.xtend @@ -16,6 +16,7 @@ package com.yakindu.solidity.ui import com.google.inject.Binder import com.google.inject.name.Names +import com.yakindu.solidity.IWorkspaceResourceResolver import com.yakindu.solidity.ui.contentassist.SolidityContentProposalPriorities import com.yakindu.solidity.ui.editor.SolidityFoldingRegionProvider import com.yakindu.solidity.ui.editor.SolidityHyperlinkHelper @@ -27,6 +28,7 @@ import com.yakindu.solidity.ui.highlighting.SoliditySemanticHighlighter import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor import org.eclipse.xtext.documentation.IEObjectDocumentationProvider import org.eclipse.xtext.formatting.IIndentationInformation +import org.eclipse.xtext.ide.editor.syntaxcoloring.ISemanticHighlightingCalculator import org.eclipse.xtext.ui.editor.contentassist.IContentProposalPriorities import org.eclipse.xtext.ui.editor.folding.IFoldingRegionProvider import org.eclipse.xtext.ui.editor.hover.DispatchingEObjectTextHover @@ -45,13 +47,13 @@ class SolidityUiModule extends AbstractSolidityUiModule { override configure(Binder binder) { super.configure(binder) - binder.bind(org.eclipse.xtext.ide.editor.syntaxcoloring.ISemanticHighlightingCalculator).to(SoliditySemanticHighlighter) + binder.bind(ISemanticHighlightingCalculator).to(SoliditySemanticHighlighter) binder.bind(IHighlightingConfiguration).to(SolidityHighlightingConfiguration) binder.bind(IEObjectDocumentationProvider).to(SolidityUserHelpDocumentationProvider) binder.bind(DispatchingEObjectTextHover).to(CrossRefObjectTextHover) binder.bind(String).annotatedWith(Names.named("stylesheet")).toInstance("/sphinx_rtd_theme.css") binder.bind(IEObjectHoverProvider).to(CustomCSSHelpHoverProvider) - + binder.bind(IWorkspaceResourceResolver).to(WorkspaceResourceResolver); } override bindIEObjectHover() { diff --git a/plugins/com.yakindu.solidity.ui/src/com/yakindu/solidity/ui/WorkspaceResourceResolver.java b/plugins/com.yakindu.solidity.ui/src/com/yakindu/solidity/ui/WorkspaceResourceResolver.java new file mode 100644 index 00000000..538f3a30 --- /dev/null +++ b/plugins/com.yakindu.solidity.ui/src/com/yakindu/solidity/ui/WorkspaceResourceResolver.java @@ -0,0 +1,16 @@ +package com.yakindu.solidity.ui; + +import java.io.File; + +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.emf.ecore.resource.Resource; + +import com.yakindu.solidity.IWorkspaceResourceResolver; + +public class WorkspaceResourceResolver implements IWorkspaceResourceResolver { + + @Override + public File resolve(Resource resource) { + return ResourcesPlugin.getWorkspace().getRoot().findMember(resource.getURI().toPlatformString(true)).getRawLocation().makeAbsolute().toFile(); + } +} diff --git a/plugins/com.yakindu.solidity.ui/src/com/yakindu/solidity/ui/quickfix/SolidityQuickfixProvider.xtend b/plugins/com.yakindu.solidity.ui/src/com/yakindu/solidity/ui/quickfix/SolidityQuickfixProvider.xtend index d325b1a0..1e816598 100644 --- a/plugins/com.yakindu.solidity.ui/src/com/yakindu/solidity/ui/quickfix/SolidityQuickfixProvider.xtend +++ b/plugins/com.yakindu.solidity.ui/src/com/yakindu/solidity/ui/quickfix/SolidityQuickfixProvider.xtend @@ -68,6 +68,7 @@ import static extension org.eclipse.xtext.EcoreUtil2.* * @author andreas muelder - Initial contribution and API * @author Florian Antony * @author Karsten Thoms + * @author Jonathan Thoene */ class SolidityQuickfixProvider extends ExpressionsQuickfixProvider { @@ -79,7 +80,7 @@ class SolidityQuickfixProvider extends ExpressionsQuickfixProvider { @Fix(WARNING_SOLIDITY_VERSION_NOT_THE_DEFAULT) def changeToDefaultPragma(Issue issue, IssueResolutionAcceptor acceptor) { - acceptor.accept(issue, 'Change version to ' + solcVersion, 'solidity version', null, + acceptor.accept(issue, '''Change version to «solcVersion»''', 'solidity version', null, new ISemanticModification() { override apply(EObject element, IModificationContext context) throws Exception { if (element instanceof PragmaSolidityDirective) { @@ -91,7 +92,7 @@ class SolidityQuickfixProvider extends ExpressionsQuickfixProvider { @Fix(ERROR_STATE_MUTABILITY_ONLY_ALLOWED_FOR_ADDRESS) def removePayableToNonAddressDeclaration(Issue issue, IssueResolutionAcceptor acceptor) { - acceptor.accept(issue, 'Remove payable declaration', 'Remove payable declaration', null, + acceptor.accept(issue, '''Remove payable declaration''', '''Remove payable declaration''', null, new ISemanticModification() { override apply(EObject element, IModificationContext context) throws Exception { if (element instanceof Parameter) { @@ -101,12 +102,20 @@ class SolidityQuickfixProvider extends ExpressionsQuickfixProvider { val fixed = document.get(node.offset, node.length).replace("payable", "") document.replace(node.offset, node.length, fixed) } + if (element instanceof VariableDefinition) { + val variable = (element as VariableDefinition) + val document = context.xtextDocument + val node = NodeModelUtils.getNode(variable) + val fixed = document.get(node.offset, node.length).replace(" payable", "") + document.replace(node.offset, node.length, fixed) + } } }) } @Fixes(@Fix(ERROR_MEMBER_TRANSFER_NOT_FOUND_OR_VISIBLE), - @Fix(ERROR_INVALID_IMPLICID_CONVERSION_TO_ADDRESS_PAYABLE)) + @Fix(ERROR_INVALID_IMPLICID_CONVERSION_TO_ADDRESS_PAYABLE), + @Fix(ERROR_MSG_VALUE_ONLY_ALLOWED_IN_PAYABLE)) def addPayableToAddressDeclaration(Issue issue, IssueResolutionAcceptor acceptor) { acceptor.accept(issue, 'Add payable to declaration', 'Add payable to declaration', null, new ISemanticModification() { @@ -117,7 +126,7 @@ class SolidityQuickfixProvider extends ExpressionsQuickfixProvider { if (typeSpecifier.type.name === SolidityTypeSystem.ADDRESS) { val document = context.xtextDocument val node = NodeModelUtils.getNode(typeSpecifier) - val fixed = document.get(node.offset, node.length) + " payable" + val fixed = document.get(node.offset, node.length) + ''' payable''' document.replace(node.offset, node.length, fixed) } } @@ -126,7 +135,7 @@ class SolidityQuickfixProvider extends ExpressionsQuickfixProvider { if (typeSpecifier.type.name === SolidityTypeSystem.ADDRESS) { val document = context.xtextDocument val node = NodeModelUtils.getNode(typeSpecifier) - val fixed = document.get(node.offset, node.length) + " payable" + val fixed = document.get(node.offset, node.length) + ''' payable''' document.replace(node.offset, node.length, fixed) } } @@ -163,7 +172,8 @@ class SolidityQuickfixProvider extends ExpressionsQuickfixProvider { null, new ISemanticModification() { override apply(EObject element, IModificationContext context) throws Exception { - if (element instanceof ArrayTypeSpecifier || element instanceof MappingTypeSpecifier) { + if (element instanceof MappingTypeSpecifier || element instanceof TypeSpecifier || element instanceof ArrayTypeSpecifier) { + (element.eContainer as Parameter).fixDeclaration(StorageLocation.CALLDATA, issue, context) } } } @@ -180,7 +190,7 @@ class SolidityQuickfixProvider extends ExpressionsQuickfixProvider { null, new ISemanticModification() { override apply(EObject element, IModificationContext context) throws Exception { - if (element instanceof TypeSpecifier) { + if (element instanceof TypeSpecifier || element instanceof ArrayTypeSpecifier) { (element.eContainer as Parameter).fixDeclaration(StorageLocation.MEMORY, issue, context) } } @@ -217,7 +227,7 @@ class SolidityQuickfixProvider extends ExpressionsQuickfixProvider { acceptor.accept(issue, 'Add \'memory\' modifier.', 'Add \'memory\' modifier.', null, new ISemanticModification() { override apply(EObject element, IModificationContext context) throws Exception { - if (element instanceof ArrayTypeSpecifier || element instanceof MappingTypeSpecifier) { + if (element instanceof ArrayTypeSpecifier || element instanceof MappingTypeSpecifier || element instanceof TypeSpecifier) { element.eContainer.fixDeclaration(StorageLocation.MEMORY, issue, context) } } @@ -225,7 +235,7 @@ class SolidityQuickfixProvider extends ExpressionsQuickfixProvider { acceptor.accept(issue, 'Add \'storage\' modifier.', 'Add \'storage\' modifier.', null, new ISemanticModification() { override apply(EObject element, IModificationContext context) throws Exception { - if (element instanceof ArrayTypeSpecifier || element instanceof MappingTypeSpecifier) { + if (element instanceof ArrayTypeSpecifier || element instanceof MappingTypeSpecifier || element instanceof TypeSpecifier) { // TODO FIXME: This is only valid IF there is no initial value, or the 'return type' of the initial value has the same storage modifier e.g. in the case of a function call. element.eContainer.fixDeclaration(StorageLocation.STORAGE, issue, context) } @@ -258,8 +268,13 @@ class SolidityQuickfixProvider extends ExpressionsQuickfixProvider { } else { val issueString = document.get(issue.offset, issue.length) val index = document.get(issue.offset, issue.length).lastIndexOf(name) - val fixed = issueString.substring(0, index) + location.literal + " " + name; - document.replace(issue.offset, issue.length, fixed) + if (index == -1 && !name.nullOrEmpty) { + val fixed = issueString + " " + location.literal; + document.replace(issue.offset, issue.length, fixed) + } else { + val fixed = issueString.substring(0, index) + location.literal + " " + name; + document.replace(issue.offset, issue.length, fixed) + } } } @@ -284,6 +299,7 @@ class SolidityQuickfixProvider extends ExpressionsQuickfixProvider { // FIXME this relates to #230 tuple expressions have multiple identifiers name = "x" } + identifier = identifier visibility = definition.visibility initialValue = definition.initialValue storage = definition.storage @@ -323,10 +339,11 @@ class SolidityQuickfixProvider extends ExpressionsQuickfixProvider { acceptor.accept(issue, 'Use "view" instead.', 'Use "view" instead.', null, new ISemanticModification() { override apply(EObject element, IModificationContext context) throws Exception { val functionDefinition = EcoreUtil2.getContainerOfType(element, FunctionDefinition) - val pure = functionDefinition.modifier.findFirst [ - it instanceof BuildInModifier && (it as BuildInModifier).type === FunctionModifier.PURE + val modifier = functionDefinition.modifier.findFirst [ + it instanceof BuildInModifier && ((it as BuildInModifier).type === FunctionModifier.PURE || + (it as BuildInModifier).type === FunctionModifier.CONSTANT) ] - pure?.changeFunctionModifierTo(FunctionModifier.VIEW) + modifier?.changeFunctionModifierTo(FunctionModifier.VIEW) } }) } @@ -362,7 +379,7 @@ class SolidityQuickfixProvider extends ExpressionsQuickfixProvider { acceptor.accept(issue, 'Use "pure" instead.', 'Use "pure" instead.', null, new ISemanticModification() { override apply(EObject element, IModificationContext context) throws Exception { if (element instanceof BuildInModifier) { - element.changeFunctionModifierTo(FunctionModifier.VIEW) + element.changeFunctionModifierTo(FunctionModifier.PURE) } } }) @@ -450,20 +467,25 @@ class SolidityQuickfixProvider extends ExpressionsQuickfixProvider { @Fix(WARNING_FILE_NO_PRAGMA_SOLIDITY) def addDefaultSolidityPragma(Issue issue, IssueResolutionAcceptor acceptor) { - acceptor.accept(issue, 'Add default solidity pragma', 'Add solidity pragma ^' + solcVersion + '.', null, + acceptor.accept(issue, 'Add default solidity pragma', 'Add solidity pragma ' + solcVersion + '.', null, new ISemanticModification() { override apply(EObject element, IModificationContext context) throws Exception { - if (element.eContainer instanceof SourceUnit) { - val sourceUnit = element.eContainer as SourceUnit - val pragma = createPragmaSolidityDirective => [ - version = "^" + solcVersion - ] - sourceUnit.pragma += pragma + if (element instanceof SourceUnit) { + element.fixPragmaSolidityDirective + } else if (element.eContainer instanceof SourceUnit) { + (element.eContainer as SourceUnit).fixPragmaSolidityDirective } } }) } + def fixPragmaSolidityDirective(SourceUnit sourceUnit) { + val pragma = createPragmaSolidityDirective => [ + version = solcVersion + ] + sourceUnit.pragma += pragma + } + @Fixes(@Fix(WARNING_DEPRECATED_SUICIDE), @Fix(ERROR_DEPRECATED_SUICIDE)) def replaceDeprecatedSuicide(Issue issue, IssueResolutionAcceptor acceptor) { @@ -723,11 +745,16 @@ class SolidityQuickfixProvider extends ExpressionsQuickfixProvider { override apply(EObject element, IModificationContext context) throws Exception { if (element instanceof FunctionDefinition) { val definition = element as FunctionDefinition - // Constant & pure exclude each other + // Constant & pure exclude each other val constant = definition.modifier.findFirst [ it | it instanceof BuildInModifier && (it as BuildInModifier).type == FunctionModifier.VIEW ] constant?.changeFunctionModifierTo(FunctionModifier.PURE) + if (constant === null) { + definition.modifier.add(0, createBuildInModifier => [ + type = FunctionModifier.PURE + ]) + } } } }) diff --git a/plugins/com.yakindu.solidity/META-INF/MANIFEST.MF b/plugins/com.yakindu.solidity/META-INF/MANIFEST.MF index 4cef884c..5c8894e7 100644 --- a/plugins/com.yakindu.solidity/META-INF/MANIFEST.MF +++ b/plugins/com.yakindu.solidity/META-INF/MANIFEST.MF @@ -15,8 +15,7 @@ Require-Bundle: org.eclipse.xtext, org.antlr.runtime;bundle-version="[3.2.0,3.2.1)", org.yakindu.base.types, org.eclipse.xtext.xbase.lib;bundle-version="2.14.0", - com.yakindu.solidity.solc, - org.eclipse.core.resources + com.yakindu.solidity.solc Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Export-Package: com.yakindu.solidity, com.yakindu.solidity.formatting2, diff --git a/plugins/com.yakindu.solidity/pom.xml b/plugins/com.yakindu.solidity/pom.xml index e7a42acb..e704211b 100644 --- a/plugins/com.yakindu.solidity/pom.xml +++ b/plugins/com.yakindu.solidity/pom.xml @@ -1,7 +1,8 @@ + xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 4.0.0 com.yakindu.solidity @@ -12,6 +13,7 @@ com.yakindu.solidity com.yakindu.solidity eclipse-plugin + @@ -19,6 +21,22 @@ + + org.eclipse.tycho + target-platform-configuration + ${tycho-version} + + + + + eclipse-feature + com.yakindu.solidity.solc.feature + 0.0.0 + + + + + maven-resources-plugin @@ -48,7 +66,7 @@ 1.3 build-helper-maven-plugin - + maven-clean-plugin diff --git a/plugins/com.yakindu.solidity/src/com/yakindu/solidity/GenerateSolidity.mwe2 b/plugins/com.yakindu.solidity/src/com/yakindu/solidity/GenerateSolidity.mwe2 index 9591fdc9..ac286e7c 100644 --- a/plugins/com.yakindu.solidity/src/com/yakindu/solidity/GenerateSolidity.mwe2 +++ b/plugins/com.yakindu.solidity/src/com/yakindu/solidity/GenerateSolidity.mwe2 @@ -40,9 +40,15 @@ Workflow { eclipsePlugin = { enabled = true } + genericIde = { + enabled = true + } createEclipseMetaData = true runtimeTest = { - enabled = false + enabled = true + } + eclipsePluginTest = { + enabled = true } } code = { diff --git a/plugins/com.yakindu.solidity/src/com/yakindu/solidity/IWorkspaceResourceResolver.java b/plugins/com.yakindu.solidity/src/com/yakindu/solidity/IWorkspaceResourceResolver.java new file mode 100644 index 00000000..bf3f8c90 --- /dev/null +++ b/plugins/com.yakindu.solidity/src/com/yakindu/solidity/IWorkspaceResourceResolver.java @@ -0,0 +1,13 @@ +package com.yakindu.solidity; + +import java.io.File; + +import org.eclipse.emf.ecore.resource.Resource; + +import com.google.inject.ImplementedBy; + +public interface IWorkspaceResourceResolver { + + public File resolve(Resource resource); + +} diff --git a/plugins/com.yakindu.solidity/src/com/yakindu/solidity/SolidityRuntimeModule.xtend b/plugins/com.yakindu.solidity/src/com/yakindu/solidity/SolidityRuntimeModule.xtend index 8b6f9c05..2595739f 100644 --- a/plugins/com.yakindu.solidity/src/com/yakindu/solidity/SolidityRuntimeModule.xtend +++ b/plugins/com.yakindu.solidity/src/com/yakindu/solidity/SolidityRuntimeModule.xtend @@ -17,11 +17,11 @@ package com.yakindu.solidity import com.google.inject.Binder import com.google.inject.name.Names -import com.yakindu.solidity.solc.ISolidityCompiler import com.yakindu.solidity.scoping.SolidityGlobalScopeProvider import com.yakindu.solidity.scoping.SolidityImportedNamespaceAwareLocalScopeProvider import com.yakindu.solidity.scoping.SolidityResourceDescriptionStrategy import com.yakindu.solidity.scoping.SolidityScopeProvider +import com.yakindu.solidity.solc.ISolidityCompiler import com.yakindu.solidity.solidity.SolidityFactory import com.yakindu.solidity.solidity.SolidityPackage import com.yakindu.solidity.terminals.SolidityValueConverterService @@ -35,6 +35,7 @@ import org.yakindu.base.types.TypesFactory import org.yakindu.base.types.TypesPackage import org.yakindu.base.types.inferrer.ITypeSystemInferrer import org.yakindu.base.types.typesystem.ITypeSystem +import com.yakindu.solidity.solc.SolidityCompiler /** * @@ -60,15 +61,7 @@ class SolidityRuntimeModule extends AbstractSolidityRuntimeModule { } private def bindCompiler(Binder binder) { - try { - val clazz = (Class.forName( - "com.yakindu.solidity.solc.SolidityCompiler") as Class) - if (clazz !== null) { - binder.bind(ISolidityCompiler).to(clazz); - } - } catch (ClassNotFoundException e) { - e.printStackTrace - } + binder.bind(ISolidityCompiler).to(SolidityCompiler); } override bindIGlobalScopeProvider() { diff --git a/plugins/com.yakindu.solidity/src/com/yakindu/solidity/formatting2/SolidityFormatter.xtend b/plugins/com.yakindu.solidity/src/com/yakindu/solidity/formatting2/SolidityFormatter.xtend index bf4e04c6..9f14db32 100644 --- a/plugins/com.yakindu.solidity/src/com/yakindu/solidity/formatting2/SolidityFormatter.xtend +++ b/plugins/com.yakindu.solidity/src/com/yakindu/solidity/formatting2/SolidityFormatter.xtend @@ -39,6 +39,7 @@ import com.yakindu.solidity.solidity.TupleExpression import com.yakindu.solidity.solidity.VariableDefinition import com.yakindu.solidity.solidity.WhileStatement import com.yakindu.solidity.solidity.InlineAssemblyBlock +import com.yakindu.solidity.solidity.FunctionalAssemblyExpression import org.eclipse.xtext.formatting2.AbstractFormatter2 import org.eclipse.xtext.formatting2.IFormattableDocument import org.eclipse.xtext.formatting2.IHiddenRegionFormatter @@ -91,7 +92,7 @@ class SolidityFormatter extends AbstractFormatter2 { } def dispatch void format(PragmaDirective it, extension IFormattableDocument document) { - prepend[noSpace] + append[newLines(1, 1, 1); priority = IHiddenRegionFormatter.LOW_PRIORITY;] } def dispatch void format(ImportDirective it, extension IFormattableDocument document) { @@ -99,6 +100,8 @@ class SolidityFormatter extends AbstractFormatter2 { } def dispatch void format(ContractDefinition it, extension IFormattableDocument document) { + prepend[newLines(2, 3, 3)] + append[newLines(3, 3, 3); priority = IHiddenRegionFormatter.HIGH_PRIORITY;] interior[indent] regionFor.keywordPairs('{', '}').forEach [ key.append[newLine; priority = IHiddenRegionFormatter.LOW_PRIORITY;].prepend [ @@ -468,6 +471,28 @@ class SolidityFormatter extends AbstractFormatter2 { ] } + def dispatch void format(FunctionalAssemblyExpression it, extension IFormattableDocument document) { + val int assemblyExpressionLength = getLengthOfAssemblyExpression + if (assemblyExpressionLength >= 80) { + regionFor.keywordPairs('(', ')').forEach [ + key.prepend[noSpace] + key.append[newLine] + value.prepend[newLine] + ] + parameters.forEach [ + prepend[newLine] + indent(document) + append[noSpace] + ] + } else { + parameters.forEach [ + prepend[oneSpace] + append[noSpace] + ] + regionFor.keyword(",").append[oneSpace].prepend[noSpace] + } + } + protected def void newLines(IHiddenRegionFormatter it) { newLines(1, 2, 3) } @@ -521,4 +546,17 @@ class SolidityFormatter extends AbstractFormatter2 { } return (functionKeywordLength + nameLength + parametersLength + modifiersLength + returnParametersLength) } + + protected def int getLengthOfAssemblyExpression(FunctionalAssemblyExpression it) { + var int labelLength = label.length + + var int parametersLength = 0// + 2(for open/close brackets) - 2(the last parameter is not followed by comma and space) + for (parameter : parameters) { + parametersLength += parameter.regionForEObject.length + parametersLength += 2//for each comma+space after parameter + } + + var sum = labelLength + parametersLength; + return sum; + } } diff --git a/plugins/com.yakindu.solidity/src/com/yakindu/solidity/validation/SolidityValidator.xtend b/plugins/com.yakindu.solidity/src/com/yakindu/solidity/validation/SolidityValidator.xtend index 5ee5e631..16985713 100644 --- a/plugins/com.yakindu.solidity/src/com/yakindu/solidity/validation/SolidityValidator.xtend +++ b/plugins/com.yakindu.solidity/src/com/yakindu/solidity/validation/SolidityValidator.xtend @@ -16,22 +16,22 @@ package com.yakindu.solidity.validation import com.google.common.collect.Sets import com.google.inject.Inject +import com.yakindu.solidity.IWorkspaceResourceResolver import com.yakindu.solidity.solc.ISolidityCompiler import com.yakindu.solidity.solc.output.FileOutputProcessor import com.yakindu.solidity.solc.output.SolidityIssueCreator +import com.yakindu.solidity.solc.preferences.ICompilerPreferences import com.yakindu.solidity.solidity.SolidityPackage import com.yakindu.solidity.solidity.SourceUnit +import java.io.File import java.util.List import java.util.Set -import org.eclipse.core.resources.IResource -import org.eclipse.core.resources.ResourcesPlugin import org.eclipse.core.runtime.SubMonitor import org.eclipse.xtext.validation.Check import org.yakindu.base.expressions.expressions.AssignmentExpression import org.yakindu.base.expressions.validation.ExpressionsValidator import org.yakindu.base.types.Expression import org.yakindu.base.types.Operation -import com.yakindu.solidity.solc.preferences.ICompilerPreferences class SolidityValidator extends ExpressionsValidator { val public SOLIDITY_VERSION_NOT_DEFAULT = "Solidity version does not match the default version" @@ -43,10 +43,13 @@ class SolidityValidator extends ExpressionsValidator { @Inject FileOutputProcessor outputWriter; + + @Inject(optional=true) + IWorkspaceResourceResolver resourceResolver; @Inject ICompilerPreferences prefs; - + override protected assertOperationArguments(Operation operation, List args) { // TODO Disabled, doesn't work with extension operations } @@ -59,15 +62,17 @@ class SolidityValidator extends ExpressionsValidator { def protected compilerValidations(SourceUnit unit) { if (compiler !== null && prefs.isCompilerEnabled) { val monitor = SubMonitor.convert(null) - val Set resources = Sets.newHashSet( - ResourcesPlugin.getWorkspace().getRoot().findMember(unit.eResource.URI.toPlatformString(true))) + if(resourceResolver === null) { + throw new IllegalStateException("Resource resolver is mandatory for compiler adoption."); + } + val Set resources = Sets.newHashSet(resourceResolver.resolve(unit.eResource)); val output = compiler.compile(resources, monitor).get issueCreator.createErrors(output.errors, resources, currentObject, messageAcceptor) issueCreator.createInfos(output.contracts, resources, currentObject, messageAcceptor) outputWriter.writeOutputFiles(output, resources); - resources.forEach [ + /*resources.forEach [ it.project.refreshLocal(IResource.DEPTH_ONE, monitor); - ] + ]*/ } } diff --git a/releng/com.yakindu.solidity.releng/pom.xml b/releng/com.yakindu.solidity.releng/pom.xml index 0ab9a4b9..90ec8b45 100644 --- a/releng/com.yakindu.solidity.releng/pom.xml +++ b/releng/com.yakindu.solidity.releng/pom.xml @@ -25,6 +25,7 @@ ../../plugins/com.yakindu.solidity.tests + ../../plugins/com.yakindu.solidity.ui.tests @@ -112,8 +113,8 @@ ../../plugins/com.yakindu.solidity.solc ../../plugins/com.yakindu.solidity.solc.linux.fragment - ../../plugins/com.yakindu.solidity.solc.win.fragment - ../../plugins/com.yakindu.solidity.solc.mac.fragment + ../../plugins/com.yakindu.solidity.solc.win32.fragment + ../../plugins/com.yakindu.solidity.solc.macosx.fragment ../../features/com.yakindu.solidity.solc.feature