Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions jetbrains-core/resources/META-INF/ext-rider.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
<component>
<implementation-class>software.aws.toolkits.jetbrains.services.lambda.LambdaHost</implementation-class>
</component>
<component>
<implementation-class>software.aws.toolkits.jetbrains.services.lambda.LambdaPsiHost</implementation-class>
</component>
</project-components>

<extensions defaultExtensionNs="com.intellij">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ public LocalLambdaRunSettingsEditorPanel(Project project) {

runtime.addActionListener(e -> {
int index = runtime.getSelectedIndex();
if (index < 0) return;
if (index < 0) {
lastSelectedRuntime = null;
return;
}
Runtime selectedRuntime = runtime.getItemAt(index);
if (selectedRuntime == lastSelectedRuntime) return;
lastSelectedRuntime = selectedRuntime;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import java.util.concurrent.TimeUnit
abstract class CachingAsyncEvaluator<TEntry, TReturn> {

companion object {
private const val EVALUATE_BLOCKING_TIMEOUT_MS = 500
private const val EVALUATE_BLOCKING_TIMEOUT_MS = 1000
}

private val logger: Logger = LoggerFactory.getLogger(this::class.java)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,12 @@ fun samRunConfiguration(project: Project): LocalLambdaRunConfiguration {
return runConfiguration
}

fun preWarmSamVersionCache(path: String?) {
fun preWarmSamVersionCache(path: String?, timeoutMs: Int = TEST_EVALUATE_BLOCKING_TIMEOUT_MS) {
path ?: throw InvalidParameterException("Test SAM CLI executable path is not set")
SamVersionCache.evaluateBlocking(path, TEST_EVALUATE_BLOCKING_TIMEOUT_MS)
SamVersionCache.evaluateBlocking(path, timeoutMs)
}

fun preWarmLambdaHandlerValidation(project: Project, runtime: Runtime, handler: String) {
fun preWarmLambdaHandlerValidation(project: Project, runtime: Runtime, handler: String, timeoutMs: Int = TEST_EVALUATE_BLOCKING_TIMEOUT_MS) {
val handlerValidator = project.service<LambdaHandlerValidator>()
handlerValidator.evaluateBlocking(LambdaHandlerValidator.LambdaEntry(project, runtime, handler), TEST_EVALUATE_BLOCKING_TIMEOUT_MS)
handlerValidator.evaluateBlocking(LambdaHandlerValidator.LambdaEntry(project, runtime, handler), timeoutMs)
}
28 changes: 28 additions & 0 deletions jetbrains-rider/ReSharper.AWS/src/AWS.Psi/Lambda/LambdaPsiHost.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using JetBrains.ProjectModel;
using JetBrains.ReSharper.Host.Features;
using JetBrains.Rider.Model;

namespace AWS.Psi.Lambda
{
[SolutionComponent]
public class LambdaPsiHost
{
private readonly LambdaPsiModel myModel;

public LambdaPsiHost(ISolution solution)
{
myModel = solution.GetProtocolSolution().GetLambdaPsiModel();

myModel.IsHandlerExists.Set((lifetime, handlerExistRequest) =>
{
var className = handlerExistRequest.ClassName;
var methodName = handlerExistRequest.MethodName;
var projectId = handlerExistRequest.ProjectId;

var backendPsiHelperModel = solution.GetProtocolSolution().GetBackendPsiHelperModel();
return backendPsiHelperModel.IsMethodExists.Handler.Invoke(
lifetime, new MethodExistingRequest(className, methodName, "", projectId));
});
}
}
}
72 changes: 59 additions & 13 deletions jetbrains-rider/protocol.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@

def protocolGroup = 'protocol'

ext.csGeneratedOutput = new File(resharperPluginPath, "src/AWS.Daemon/Protocol")
ext.csDaemonGeneratedOutput = new File(resharperPluginPath, "src/AWS.Daemon/Protocol")
ext.csPsiGeneratedOutput = new File(resharperPluginPath, "src/AWS.Psi/Protocol")

ext.ktGeneratedOutput = new File(projectDir, "src/software/aws/toolkits/jetbrains/protocol")

task generateModel(type: tasks.getByName("rdgen").class) {
group = protocolGroup
description = 'Generates protocol models'
ext.modelDir = new File(projectDir, "protocol/model")

def modelDir = new File(projectDir, "protocol/model")
task generateDaemonModel(type: tasks.getByName("rdgen").class) {
def daemonModelSource = new File(modelDir, "daemon").canonicalPath

// NOTE: classpath is evaluated lazily, at execution time, because it comes from the unzipped
// intellij SDK, which is extracted in afterEvaluate
Expand All @@ -26,8 +27,8 @@ task generateModel(type: tasks.getByName("rdgen").class) {

"$rdLibDirectory/rider-model.jar"
}
sources modelDir.canonicalPath
packages = "protocol.model"
sources daemonModelSource
packages = "protocol.model.daemon"

generator {
language = "kotlin"
Expand All @@ -42,21 +43,66 @@ task generateModel(type: tasks.getByName("rdgen").class) {
transform = "reversed"
root = "com.jetbrains.rider.model.nova.ide.IdeRoot"
namespace = "JetBrains.Rider.Model"
directory = "$csGeneratedOutput"
directory = "$csDaemonGeneratedOutput"
}
}
}

task generatePsiModel(type: tasks.getByName("rdgen").class) {
def psiModelSource = new File(modelDir, "psi").canonicalPath

// NOTE: classpath is evaluated lazily, at execution time, because it comes from the unzipped
// intellij SDK, which is extracted in afterEvaluate
params {
verbose = true
hashFolder = "build/rdgen"

logger.info("Configuring rdgen params")
classpath {
logger.info("Calculating classpath for rdgen, intellij.ideaDependency is: ${intellij.ideaDependency}")
def sdkPath = intellij.ideaDependency.classes
def rdLibDirectory = new File(sdkPath, "lib/rd").canonicalFile

"$rdLibDirectory/rider-model.jar"
}
sources psiModelSource
packages = "protocol.model.psi"

generator {
language = "kotlin"
transform = "asis"
root = "com.jetbrains.rider.model.nova.ide.IdeRoot"
namespace = "com.jetbrains.rider.model"
directory = "$ktGeneratedOutput"
}

generator {
language = "csharp"
transform = "reversed"
root = "com.jetbrains.rider.model.nova.ide.IdeRoot"
namespace = "JetBrains.Rider.Model"
directory = "$csPsiGeneratedOutput"
}
}
}

task generateModel(type: tasks.getByName("rdgen").class) {
group = protocolGroup
description = 'Generates protocol models'

dependsOn generateDaemonModel, generatePsiModel
}

task cleanProtocolModels {
group = protocolGroup
description = 'Clean up generated protocol models'

if (csGeneratedOutput.isDirectory()) {
csGeneratedOutput.deleteDir()
}
def protocolOutDirs = [ ktGeneratedOutput, csDaemonGeneratedOutput, csPsiGeneratedOutput ]

if (ktGeneratedOutput.isDirectory()) {
ktGeneratedOutput.deleteDir()
for (dir in protocolOutDirs) {
if (dir.isDirectory()) {
dir.deleteDir()
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package protocol.model
package protocol.model.daemon

import com.jetbrains.rd.generator.nova.Ext
import com.jetbrains.rd.generator.nova.doc
Expand Down
29 changes: 29 additions & 0 deletions jetbrains-rider/protocol/model/psi/LambdaPsiModel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package protocol.model.psi

import com.jetbrains.rd.generator.nova.Ext
import com.jetbrains.rd.generator.nova.async
import com.jetbrains.rd.generator.nova.call
import com.jetbrains.rd.generator.nova.doc
import com.jetbrains.rd.generator.nova.field
import com.jetbrains.rd.generator.nova.PredefinedType.bool
import com.jetbrains.rd.generator.nova.PredefinedType.int
import com.jetbrains.rd.generator.nova.PredefinedType.string
import com.jetbrains.rider.model.nova.ide.SolutionModel

@Suppress("unused")
object LambdaPsiModel : Ext(SolutionModel.Solution) {

private val HandlerExistRequest = structdef {
field("className", string)
field("methodName", string)
field("projectId", int)
}

init {
call("isHandlerExists", HandlerExistRequest, bool).async
.doc("Check whether handler with specified name exists for a partucular project")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.lambda

import com.intellij.openapi.project.Project
import com.jetbrains.rdclient.util.idea.LifetimedProjectComponent
import com.jetbrains.rider.model.lambdaPsiModel
import com.jetbrains.rider.projectView.solution

@Suppress("ComponentNotRegistered")
class LambdaPsiHost(project: Project) : LifetimedProjectComponent(project) {

val model = project.solution.lambdaPsiModel
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,26 @@

package software.aws.toolkits.jetbrains.services.lambda.dotnet

import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.NavigatablePsiElement
import com.intellij.psi.PsiElement
import com.intellij.psi.search.GlobalSearchScope
import com.jetbrains.rd.framework.impl.RpcTimeouts
import com.jetbrains.rd.util.lifetime.Lifetime
import com.jetbrains.rd.util.threading.SpinWait
import com.jetbrains.rider.model.MethodExistingRequest
import com.jetbrains.rider.model.backendPsiHelperModel
import com.jetbrains.rider.model.publishableProjectsModel
import com.jetbrains.rider.model.HandlerExistRequest
import com.jetbrains.rider.model.MethodExistingRequest
import com.jetbrains.rider.projectView.ProjectModelViewHost
import com.jetbrains.rider.projectView.solution
import com.jetbrains.rider.run.configurations.method.getProjectModeId
import com.jetbrains.rider.util.idea.application
import com.jetbrains.rider.util.idea.getComponent
import software.aws.toolkits.jetbrains.services.lambda.LambdaHandlerResolver
import software.aws.toolkits.jetbrains.services.lambda.LambdaPsiHost
import software.aws.toolkits.jetbrains.services.lambda.dotnet.element.RiderLambdaHandlerFakePsiElement
import java.time.Duration

class DotNetLambdaHandlerResolver : LambdaHandlerResolver {

companion object {
private const val handlerValidationTimeoutMs = 2000L
private const val findMethodTimeoutMs = 10000L
}

override fun version(): Int = 1

override fun findPsiElements(
Expand Down Expand Up @@ -58,24 +51,7 @@ class DotNetLambdaHandlerResolver : LambdaHandlerResolver {
val type = handlerParts[1]
val methodName = handlerParts[2]

var isMethodExists = false

if (application.isDispatchThread) {
isMethodExists = isMethodExists(project, assemblyName, type, methodName)
} else {
var isCompleted = false
application.invokeLater {
isMethodExists = isMethodExists(project, assemblyName, type, methodName)
isCompleted = true
}

SpinWait.spinUntil(Lifetime.Eternal, Duration.ofMillis(handlerValidationTimeoutMs)) {
ProgressManager.checkCanceled()
isCompleted
}
}

return isMethodExists
return isMethodExists(project, assemblyName, type, methodName)
}

fun getFieldIdByHandlerName(project: Project, handler: String): Int {
Expand All @@ -97,7 +73,7 @@ class DotNetLambdaHandlerResolver : LambdaHandlerResolver {
methodName = methodName,
targetFramework = "",
projectId = projectModelViewHost.getProjectModeId(projectToProcess.projectFilePath)),
timeouts = RpcTimeouts(findMethodTimeoutMs, findMethodTimeoutMs)
timeouts = RpcTimeouts.default
)

return fileIdResponse?.fileId ?: -1
Expand All @@ -108,12 +84,12 @@ class DotNetLambdaHandlerResolver : LambdaHandlerResolver {
val projects = project.solution.publishableProjectsModel.publishableProjects.values.toList()
val projectToProcess = projects.find { it.projectName == assemblyName } ?: return false

return project.solution.backendPsiHelperModel.isMethodExists
.sync(MethodExistingRequest(
className = type,
methodName = methodName,
targetFramework = "",
projectId = projectModelViewHost.getProjectModeId(projectToProcess.projectFilePath)
), RpcTimeouts.default)
val model = project.getComponent<LambdaPsiHost>().model

return model.isHandlerExists.sync(HandlerExistRequest(
className = type,
methodName = methodName,
projectId = projectModelViewHost.getProjectModeId(projectToProcess.projectFilePath)
))
}
}
Loading