blob: ca19ef6ed760db115e52827a844078d401aaf621 [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.dsl.toplevel.scopes
import com.intellij.psi.SyntheticElement
import org.jetbrains.plugins.groovy.dsl.toplevel.*
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames
import static com.intellij.patterns.PlatformPatterns.*
import static com.intellij.patterns.PsiJavaPatterns.psiClass
import static com.intellij.patterns.StandardPatterns.*
import static org.jetbrains.plugins.groovy.lang.psi.patterns.GrAnnotationPattern.annotation
import static org.jetbrains.plugins.groovy.lang.psi.patterns.GroovyPatterns.groovyScript
import static org.jetbrains.plugins.groovy.lang.psi.patterns.GroovyPatterns.methodCall
/**
* @author ilyas
*/
abstract class Scope {
abstract List<ContextFilter> createFilters(Map args)
}
class ClassScope extends Scope {
private final String namePattern
ClassScope(Map args) {
namePattern = args && args.name ? args.name : /.*/
}
List<ContextFilter> createFilters(Map args) {
if (namePattern) {
def match = string().matches(namePattern)
return [new PlaceContextFilter(psiElement().inside(
or(
psiClass().withQualifiedName(match),
psiClass().withName(match))))]
}
return []
}
}
class ClosureScope extends Scope {
private final boolean isArg
final String methodName
final String annotationName
ClosureScope(Map args) {
isArg = args?.isArgument
methodName = args?.methodName
annotationName = args?.annotationName
}
def isArg() {
isArg
}
List<ContextFilter> createFilters(Map args) {
def result = []
result << new PlaceContextFilter(psiElement().inside(GrClosableBlock))
final scope = (ClosureScope)args.scope
if (scope.isArg()) {
result << new PlaceContextFilter(
psiElement().inside(
psiElement(GrClosableBlock).withParent(
or(
psiElement(GrCall),
psiElement(GrArgumentList).withParent(GrCall)))))
}
if (scope.methodName != null) {
result << new PlaceContextFilter(psiElement().inside(
psiElement(GrClosableBlock).withParent(
or(
methodCall().withMethodName(scope.methodName),
psiElement(GrArgumentList).withParent(
methodCall().withMethodName(scope.methodName))))))
}
if (scope.annotationName != null) {
result << new PlaceContextFilter(psiElement().inside(
psiElement(GrClosableBlock).inside(
annotation().withQualifiedName(scope.annotationName))))
}
// Enhance only unqualified expressions
if (!args.ctype) {
result << ClassContextFilter.subtypeOf(GroovyCommonClassNames.GROOVY_LANG_CLOSURE)
}
result
}
}
class ScriptScope extends Scope {
final String namePattern
final String extension
ScriptScope(Map args) {
if (args) {
if (args.name) {
namePattern = args.name
}
else if (args.extension) {
extension = args.extension
}
}
}
List<ContextFilter> createFilters(Map args) {
def result = []
def scriptPattern = groovyScript()
if (extension) {
scriptPattern = scriptPattern.withVirtualFile(virtualFile().withExtension(extension))
}
result << new FileContextFilter(scriptPattern)
// Name matcher
if (namePattern) {
result << new FileContextFilter(psiFile().withName(string().matches(namePattern)))
}
// Process unqualified references only
if (!args.ctype) {
result << ClassContextFilter.fromClassPattern(psiClass().and(instanceOf(SyntheticElement)))
}
return result
}
}
class AnnotatedScope extends Scope {
final String annoQName
def AnnotatedScope(Map args) {
if (args && args.ctype) {
annoQName = args.ctype
}
}
List<ContextFilter> createFilters(Map args) {
annoQName ? [new AnnotatedContextFilter(annoQName)] : []
}
}