mirror of
https://github.com/sigmasternchen/xtext-core
synced 2025-03-16 08:48:55 +00:00
Merge pull request #968 from eclipse/ak/bug_489745
[bug 489745] Call Hierarchy View
This commit is contained in:
commit
41ca067f19
24 changed files with 801 additions and 11 deletions
File diff suppressed because one or more lines are too long
|
@ -8,14 +8,21 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
|||
Bundle-ActivationPolicy: lazy
|
||||
Bundle-Vendor: %providerName
|
||||
Require-Bundle: org.eclipse.xtext;visibility:=reexport,
|
||||
org.eclipse.xtend.lib
|
||||
org.eclipse.xtend.lib,
|
||||
org.eclipse.core.runtime
|
||||
Import-Package: org.apache.log4j;version="1.2.15"
|
||||
Export-Package: org.eclipse.xtext.ide;x-friends:="org.eclipse.xtend.ide",
|
||||
org.eclipse.xtext.ide.editor.bracketmatching;x-friends:="org.eclipse.xtend.ide.common,org.eclipse.xtend.ide",
|
||||
org.eclipse.xtext.ide.editor.contentassist,
|
||||
org.eclipse.xtext.ide.editor.contentassist.antlr,
|
||||
org.eclipse.xtext.ide.editor.contentassist.antlr.internal,
|
||||
org.eclipse.xtext.ide.editor.hierarchy;
|
||||
x-friends:="org.eclipse.xtext.junit4,
|
||||
org.eclipse.xtext.xtext.ui,
|
||||
org.eclipse.xtext.xtext.ui.tests,
|
||||
org.eclipse.xtext.example.arithmetics.ui",
|
||||
org.eclipse.xtext.ide.editor.model,
|
||||
org.eclipse.xtext.ide.editor.navigation,
|
||||
org.eclipse.xtext.ide.editor.partialEditing,
|
||||
org.eclipse.xtext.ide.editor.syntaxcoloring,
|
||||
org.eclipse.xtext.ide.labels;x-friends:="org.eclipse.xtext.web"
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.editor.hierarchy
|
||||
|
||||
import com.google.inject.Inject
|
||||
import javax.inject.Provider
|
||||
import org.eclipse.xtend.lib.annotations.Accessors
|
||||
import org.eclipse.xtext.findReferences.IReferenceFinder
|
||||
import org.eclipse.xtext.findReferences.IReferenceFinder.IResourceAccess
|
||||
import org.eclipse.xtext.findReferences.TargetURICollector
|
||||
import org.eclipse.xtext.findReferences.TargetURIs
|
||||
import org.eclipse.xtext.resource.IResourceDescriptions
|
||||
import org.eclipse.xtext.resource.IResourceServiceProvider
|
||||
|
||||
/**
|
||||
* @author kosyakov - Initial contribution and API
|
||||
* @since 2.10
|
||||
*/
|
||||
@Accessors(PUBLIC_SETTER, PROTECTED_GETTER)
|
||||
abstract class AbstractHierarchyBuilder implements HierarchyBuilder {
|
||||
|
||||
IResourceAccess resourceAccess
|
||||
|
||||
IResourceDescriptions indexData
|
||||
|
||||
@Inject
|
||||
IReferenceFinder referenceFinder
|
||||
|
||||
@Inject
|
||||
TargetURICollector targetURICollector
|
||||
|
||||
@Inject
|
||||
Provider<TargetURIs> targetURIProvider
|
||||
|
||||
@Inject
|
||||
HierarchyNodeLocationProvider hierarchyNodeLocationProvider
|
||||
|
||||
@Inject
|
||||
IResourceServiceProvider.Registry resourceServiceProviderRegistry
|
||||
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.editor.hierarchy
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor
|
||||
import org.eclipse.emf.common.util.URI
|
||||
import org.eclipse.emf.ecore.EObject
|
||||
import org.eclipse.xtext.findReferences.ReferenceAcceptor
|
||||
import org.eclipse.xtext.findReferences.TargetURIs
|
||||
import org.eclipse.xtext.resource.IEObjectDescription
|
||||
import org.eclipse.xtext.resource.IReferenceDescription
|
||||
import org.eclipse.xtext.util.ITextRegionWithLineInformation
|
||||
|
||||
import static extension org.eclipse.emf.ecore.util.EcoreUtil.*
|
||||
import static extension org.eclipse.xtext.nodemodel.util.NodeModelUtils.*
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Default implementation of a call hierarchy builder.
|
||||
* </p>
|
||||
*
|
||||
* @author kosyakov - Initial contribution and API
|
||||
* @since 2.10
|
||||
*/
|
||||
class DefaultCallHierarchyBuilder extends AbstractHierarchyBuilder {
|
||||
|
||||
override buildRoots(URI rootURI, IProgressMonitor progressMonitor) {
|
||||
val rootDeclaration = rootURI.rootDeclaration
|
||||
if(rootDeclaration === null) return emptyList
|
||||
return #[rootDeclaration.createRoot]
|
||||
}
|
||||
|
||||
override buildChildren(HierarchyNode parent, IProgressMonitor progressMonitor) {
|
||||
if (!parent.mayHaveChildren)
|
||||
return emptyList
|
||||
|
||||
val children = newLinkedHashMap
|
||||
parent.element.EObjectURI.findDeclarations(progressMonitor) [ declaration, reference |
|
||||
var childNode = children.get(declaration.EObjectURI)
|
||||
if (childNode === null) {
|
||||
childNode = createChild(declaration, parent)
|
||||
children.put(declaration.EObjectURI, childNode)
|
||||
}
|
||||
childNode.locations += reference.createLocation
|
||||
]
|
||||
return children.values
|
||||
}
|
||||
|
||||
protected def void findDeclarations(
|
||||
URI targetURI,
|
||||
IProgressMonitor progressMonitor,
|
||||
(IEObjectDescription, IReferenceDescription)=>void acceptor
|
||||
) {
|
||||
val targetURIs = targetURI.collectTargetURIs
|
||||
|
||||
referenceFinder.findAllReferences(
|
||||
targetURIs,
|
||||
resourceAccess,
|
||||
indexData,
|
||||
new ReferenceAcceptor(resourceServiceProviderRegistry) [ reference |
|
||||
val declaration = reference.declaration
|
||||
if (declaration !== null)
|
||||
acceptor.apply(declaration, reference)
|
||||
],
|
||||
progressMonitor
|
||||
)
|
||||
}
|
||||
|
||||
protected def TargetURIs collectTargetURIs(URI targetURI) {
|
||||
val targetURIs = targetURIProvider.get
|
||||
if(targetURI === null) return targetURIs
|
||||
|
||||
return resourceAccess.readOnly(targetURI) [ resourceSet |
|
||||
val targetObject = resourceSet.getEObject(targetURI, true)
|
||||
if(targetObject === null) return targetURIs
|
||||
|
||||
targetURICollector.add(targetObject, targetURIs)
|
||||
return targetURIs
|
||||
]
|
||||
}
|
||||
|
||||
protected def IEObjectDescription getRootDeclaration(URI rootURI) {
|
||||
return rootURI.declaration.rootDeclaration
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns a declaration representing a root hierarchy node for the given element; can return <code>null<code> if the hierarchy does not support such kind of declarations
|
||||
*/
|
||||
protected def IEObjectDescription getRootDeclaration(IEObjectDescription declaration) {
|
||||
return declaration
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns a declaration representing a child node that can be reached with the given reference; can return <code>null</code> if the hierarchy does not support such kind of references
|
||||
*/
|
||||
protected def IEObjectDescription getDeclaration(IReferenceDescription reference) {
|
||||
if(reference === null) return null
|
||||
|
||||
val declarationURI = reference.containerEObjectURI ?: reference.sourceEObjectUri
|
||||
return declarationURI.declaration
|
||||
}
|
||||
|
||||
protected def IEObjectDescription getDeclaration(URI declarationURI) {
|
||||
val resourceDescription = indexData.getResourceDescription(declarationURI.trimFragment)
|
||||
if(resourceDescription === null) return null
|
||||
|
||||
return resourceDescription.exportedObjects.findFirst[EObjectURI == declarationURI]
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns a root hierarchy node for the given declaration; cannot be <code>null</code>
|
||||
*/
|
||||
protected def HierarchyNode createRoot(IEObjectDescription declaration) {
|
||||
val node = new DefaultHierarchyNode
|
||||
node.element = declaration
|
||||
node.mayHaveChildren = true
|
||||
return node
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns a child node for the given declaration and the parent node; cannot be <code>null</code>
|
||||
*/
|
||||
protected def HierarchyNode createChild(IEObjectDescription declaration, HierarchyNode parent) {
|
||||
val node = new DefaultHierarchyNode
|
||||
node.parent = parent
|
||||
node.element = declaration
|
||||
node.mayHaveChildren = !node.recursive
|
||||
return node
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns a location for the given reference; cannot be <code>null</code>
|
||||
*/
|
||||
protected def HierarchyNodeLocation createLocation(IReferenceDescription reference) {
|
||||
return resourceAccess.readOnly(reference.sourceEObjectUri) [ resourceSet |
|
||||
val obj = resourceSet.getEObject(reference.sourceEObjectUri, true)
|
||||
val textRegion = obj.getTextRegion(reference)
|
||||
val text = obj.getText(textRegion)
|
||||
return new DefaultHierarchyNodeLocation(text, textRegion, reference)
|
||||
]
|
||||
}
|
||||
|
||||
protected def ITextRegionWithLineInformation getTextRegion(EObject obj, IReferenceDescription reference) {
|
||||
return hierarchyNodeLocationProvider.getTextRegion(obj, reference.EReference, reference.indexInList)
|
||||
}
|
||||
|
||||
protected def String getText(EObject obj, ITextRegionWithLineInformation textRegion) {
|
||||
if (obj === null || textRegion === ITextRegionWithLineInformation.EMPTY_REGION)
|
||||
return ''
|
||||
|
||||
val node = obj.rootContainer.node
|
||||
if (node === null)
|
||||
return ''
|
||||
|
||||
val endOffset = textRegion.offset + textRegion.length
|
||||
return node.rootNode.text.substring(textRegion.offset, endOffset)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.editor.hierarchy
|
||||
|
||||
import org.eclipse.xtend.lib.annotations.Accessors
|
||||
import org.eclipse.xtext.resource.IEObjectDescription
|
||||
import org.eclipse.xtext.util.Wrapper
|
||||
|
||||
/**
|
||||
* @author kosyakov - Initial contribution and API
|
||||
* @since 2.10
|
||||
*/
|
||||
class DefaultHierarchyNode implements HierarchyNode {
|
||||
|
||||
@Accessors
|
||||
HierarchyNode parent
|
||||
|
||||
@Accessors(PUBLIC_SETTER)
|
||||
boolean mayHaveChildren
|
||||
|
||||
@Accessors
|
||||
IEObjectDescription element
|
||||
|
||||
@Accessors(PUBLIC_GETTER)
|
||||
val locations = <HierarchyNodeLocation>newArrayList
|
||||
|
||||
Wrapper<Boolean> recursive
|
||||
|
||||
override getNavigationElement() {
|
||||
return locations.head ?: element
|
||||
}
|
||||
|
||||
override boolean isRecursive() {
|
||||
if (recursive === null)
|
||||
recursive = Wrapper.wrap(internalIsRecursive)
|
||||
return recursive.get
|
||||
}
|
||||
|
||||
protected def boolean internalIsRecursive() {
|
||||
var node = parent
|
||||
while (node !== null) {
|
||||
if (node.element.EObjectURI == element.EObjectURI)
|
||||
return true
|
||||
node = node.parent
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override mayHaveChildren() {
|
||||
mayHaveChildren
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.editor.hierarchy
|
||||
|
||||
import org.eclipse.xtend.lib.annotations.Accessors
|
||||
import org.eclipse.xtend.lib.annotations.Delegate
|
||||
import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
|
||||
import org.eclipse.xtext.util.ITextRegionWithLineInformation
|
||||
|
||||
/**
|
||||
* @author kosyakov - Initial contribution and API
|
||||
* @since 2.10
|
||||
*/
|
||||
@Accessors
|
||||
@FinalFieldsConstructor
|
||||
class DefaultHierarchyNodeLocation implements HierarchyNodeLocation {
|
||||
val String text
|
||||
@Delegate
|
||||
val ITextRegionWithLineInformation textRegion
|
||||
val Object navigationElement
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.editor.hierarchy
|
||||
|
||||
import com.google.inject.Inject
|
||||
import com.google.inject.Singleton
|
||||
import org.eclipse.emf.ecore.EObject
|
||||
import org.eclipse.emf.ecore.EStructuralFeature
|
||||
import org.eclipse.xtext.resource.ILocationInFileProvider
|
||||
import org.eclipse.xtext.util.ITextRegion
|
||||
import org.eclipse.xtext.util.ITextRegionWithLineInformation
|
||||
import org.eclipse.xtext.util.TextRegionWithLineInformation
|
||||
|
||||
import static extension org.eclipse.xtext.nodemodel.util.NodeModelUtils.*
|
||||
|
||||
/**
|
||||
* @author kosyakov - Initial contribution and API
|
||||
* @since 2.10
|
||||
*/
|
||||
@Singleton
|
||||
class DefaultHierarchyNodeLocationProvider implements HierarchyNodeLocationProvider {
|
||||
|
||||
@Inject
|
||||
protected ILocationInFileProvider locationInFileProvider
|
||||
|
||||
override getTextRegion(EObject obj) {
|
||||
if(obj === null) return ITextRegionWithLineInformation.EMPTY_REGION
|
||||
|
||||
val textRegion = locationInFileProvider.getSignificantTextRegion(obj)
|
||||
return obj.toTextRegionWithLineInformation(textRegion)
|
||||
}
|
||||
|
||||
override getTextRegion(EObject owner, EStructuralFeature feature, int indexInList) {
|
||||
if(owner === null) return ITextRegionWithLineInformation.EMPTY_REGION
|
||||
|
||||
val textRegion = locationInFileProvider.getSignificantTextRegion(owner, feature, indexInList)
|
||||
return owner.toTextRegionWithLineInformation(textRegion)
|
||||
}
|
||||
|
||||
protected def toTextRegionWithLineInformation(EObject obj, ITextRegion textRegion) {
|
||||
if (textRegion === null)
|
||||
return ITextRegionWithLineInformation.EMPTY_REGION
|
||||
|
||||
if (textRegion instanceof ITextRegionWithLineInformation)
|
||||
return textRegion
|
||||
|
||||
val node = obj.node
|
||||
if (node === null) {
|
||||
return new TextRegionWithLineInformation(textRegion.offset, textRegion.length, 0, 0)
|
||||
}
|
||||
val startLine = node.getLineAndColumn(textRegion.offset).line - 1
|
||||
val endLine = node.getLineAndColumn(textRegion.offset + textRegion.length).line - 1
|
||||
return new TextRegionWithLineInformation(textRegion.offset, textRegion.length, startLine, endLine)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.editor.hierarchy
|
||||
|
||||
import org.eclipse.xtend.lib.annotations.Accessors
|
||||
|
||||
/**
|
||||
* @author kosyakov - Initial contribution and API
|
||||
* @since 2.10
|
||||
*/
|
||||
@Accessors
|
||||
class DefaultHierarchyRoot implements HierarchyRoot {
|
||||
val roots = <HierarchyNode>newArrayList
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.editor.hierarchy
|
||||
|
||||
import java.util.Collection
|
||||
import org.eclipse.core.runtime.IProgressMonitor
|
||||
import org.eclipse.emf.common.util.URI
|
||||
|
||||
/**
|
||||
* This class is used to build a hierarchy structure.
|
||||
*
|
||||
* @author kosyakov - Initial contribution and API
|
||||
* @since 2.10
|
||||
*/
|
||||
interface HierarchyBuilder {
|
||||
|
||||
/**
|
||||
* @returns root hierarchy nodes for the given URI; empty if the hierarchy cannot be built for the given URI
|
||||
*/
|
||||
def Collection<HierarchyNode> buildRoots(URI rootURI, IProgressMonitor monitor)
|
||||
|
||||
/**
|
||||
* @returns child nodes for the given parent node; empty if {@link HierarchyNode#mayHaveChildren} returns <code>false</code> for the parent
|
||||
*/
|
||||
def Collection<HierarchyNode> buildChildren(HierarchyNode parent, IProgressMonitor monitor)
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.editor.hierarchy
|
||||
|
||||
import java.util.Collection
|
||||
import org.eclipse.xtext.ide.editor.navigation.Navigatable
|
||||
import org.eclipse.xtext.resource.IEObjectDescription
|
||||
|
||||
/**
|
||||
* Represents a hierarchy node.
|
||||
*
|
||||
* @author kosyakov - Initial contribution and API
|
||||
* @since 2.10
|
||||
*/
|
||||
interface HierarchyNode extends Navigatable {
|
||||
|
||||
/**
|
||||
* @returns an associated element that is used to build child nodes
|
||||
*/
|
||||
def IEObjectDescription getElement()
|
||||
|
||||
/**
|
||||
* @returns a parent; <code>null</code> if the node is a root
|
||||
*/
|
||||
def HierarchyNode getParent()
|
||||
|
||||
/**
|
||||
* @returns locations used to reach the node from a parent; empty if the node is a root
|
||||
*/
|
||||
def Collection<HierarchyNodeLocation> getLocations()
|
||||
|
||||
/**
|
||||
* @returns whether there is a parent (can be transitive) containing the same element as the node
|
||||
*/
|
||||
def boolean isRecursive()
|
||||
|
||||
/**
|
||||
* @returns whether the node may have children; e.g. a recursive node cannot have children
|
||||
*/
|
||||
def boolean mayHaveChildren()
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.editor.hierarchy
|
||||
|
||||
import org.eclipse.xtext.ide.editor.navigation.Navigatable
|
||||
import org.eclipse.xtext.util.ITextRegionWithLineInformation
|
||||
|
||||
/**
|
||||
* Represents a reference between parent and child nodes. Each location is backed up with a region and a text.
|
||||
*
|
||||
* @author kosyakov - Initial contribution and API
|
||||
* @since 2.10
|
||||
*/
|
||||
interface HierarchyNodeLocation extends Navigatable, ITextRegionWithLineInformation {
|
||||
def String getText()
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.editor.hierarchy
|
||||
|
||||
import com.google.inject.ImplementedBy
|
||||
import org.eclipse.emf.ecore.EObject
|
||||
import org.eclipse.emf.ecore.EStructuralFeature
|
||||
import org.eclipse.xtext.util.ITextRegionWithLineInformation
|
||||
|
||||
/**
|
||||
* This class is used to identify a region for {@link HierarchyNode} and {@link HierarchyNodeLocation}.
|
||||
* @author kosyakov - Initial contribution and API
|
||||
* @since 2.10
|
||||
*/
|
||||
@ImplementedBy(DefaultHierarchyNodeLocationProvider)
|
||||
interface HierarchyNodeLocationProvider {
|
||||
def ITextRegionWithLineInformation getTextRegion(EObject obj)
|
||||
|
||||
def ITextRegionWithLineInformation getTextRegion(EObject owner, EStructuralFeature feature, int indexInList)
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.editor.hierarchy
|
||||
|
||||
import java.util.Collection
|
||||
|
||||
/**
|
||||
* Represents a hierarchy root.
|
||||
*
|
||||
* @author kosyakov - Initial contribution and API
|
||||
* @since 2.10
|
||||
*/
|
||||
interface HierarchyRoot {
|
||||
|
||||
def Collection<HierarchyNode> getRoots()
|
||||
|
||||
val EMPTY = new HierarchyRoot() {
|
||||
|
||||
override getRoots() {
|
||||
emptyList
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.editor.navigation
|
||||
|
||||
/**
|
||||
* Represents an instance that can be opened in an editor.
|
||||
*
|
||||
* @author kosyakov - Initial contribution and API
|
||||
* @since 2.10
|
||||
*/
|
||||
interface Navigatable {
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Returns an instance containing enough information to identify an editor that should be opened and a region that should be revealed.
|
||||
* </p>
|
||||
* <p>
|
||||
* Typical navigation elements are resource, object and reference descriptions as well as another navigatable element.
|
||||
* </p>
|
||||
* <p>
|
||||
* Avoid usage of resource sets, resources and eobjects as navigation elements, since it can lead to memory leaks.
|
||||
* </p>
|
||||
*/
|
||||
def Object getNavigationElement()
|
||||
}
|
|
@ -8,7 +8,8 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
|||
Export-Package: org.eclipse.xtext.junit4,
|
||||
org.eclipse.xtext.junit4.build,
|
||||
org.eclipse.xtext.junit4.formatter;x-friends:="org.eclipse.xtext.xbase.tests",
|
||||
org.eclipse.xtext.junit4.internal;x-friends:="org.eclipse.xtext.tests,org.eclipse.xtext.junit4.tests",
|
||||
org.eclipse.xtext.junit4.ide;x-friends:="org.eclipse.xtext.xtext.ui.tests",
|
||||
org.eclipse.xtext.junit4.internal;x-friends:="org.eclipse.xtext.tests,org.eclipse.xtext.junit4.tests,org.eclipse.xtext.xtext.ui.tests",
|
||||
org.eclipse.xtext.junit4.logging;x-internal:=true,
|
||||
org.eclipse.xtext.junit4.serializer;x-internal:=true,
|
||||
org.eclipse.xtext.junit4.smoketest,
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.junit4.ide
|
||||
|
||||
import com.google.inject.Inject
|
||||
import java.util.Collection
|
||||
import javax.inject.Provider
|
||||
import org.eclipse.emf.common.util.URI
|
||||
import org.eclipse.emf.ecore.resource.ResourceSet
|
||||
import org.eclipse.xtend.lib.annotations.Accessors
|
||||
import org.eclipse.xtext.ide.editor.hierarchy.AbstractHierarchyBuilder
|
||||
import org.eclipse.xtext.ide.editor.hierarchy.HierarchyBuilder
|
||||
import org.eclipse.xtext.ide.editor.hierarchy.HierarchyNode
|
||||
import org.eclipse.xtext.ide.editor.hierarchy.HierarchyNodeLocation
|
||||
import org.eclipse.xtext.junit4.validation.ValidationTestHelper
|
||||
import org.eclipse.xtext.resource.EObjectAtOffsetHelper
|
||||
import org.eclipse.xtext.resource.IResourceDescriptionsProvider
|
||||
import org.eclipse.xtext.resource.XtextResource
|
||||
import org.eclipse.xtext.resource.XtextResourceSet
|
||||
import org.eclipse.xtext.ui.editor.findrefs.SimpleLocalResourceAccess
|
||||
import org.eclipse.xtext.util.LazyStringInputStream
|
||||
|
||||
import static org.junit.Assert.*
|
||||
|
||||
import static extension org.eclipse.xtext.EcoreUtil2.*
|
||||
|
||||
/**
|
||||
* @author kosyakov - Initial contribution and API
|
||||
* @since 2.10
|
||||
*/
|
||||
abstract class AbstractHierarchyBuilderTest {
|
||||
|
||||
@Inject
|
||||
extension ValidationTestHelper
|
||||
|
||||
@Inject
|
||||
extension EObjectAtOffsetHelper
|
||||
|
||||
@Inject
|
||||
Provider<XtextResourceSet> resourceSetProvider
|
||||
|
||||
@Inject
|
||||
IResourceDescriptionsProvider resourceDescriptionsProvider
|
||||
|
||||
protected def testBuildHierarchy((HierarchyBuilderTestConfiguration)=>void configurator) {
|
||||
val extension configuration = new HierarchyBuilderTestConfiguration
|
||||
configurator.apply(configuration)
|
||||
|
||||
val resourceSet = configuration.createResourceSet
|
||||
val hierarchyBuilder = hierarchyBuilderProvider.apply(resourceSet)
|
||||
|
||||
val resourceURI = if(resourceURI === null) models.last.key else resourceURI
|
||||
val resource = resourceSet.getResource(URI.createURI(resourceURI), false) as XtextResource
|
||||
val rootURI = resource.resolveElementAt(index).platformResourceOrNormalizedURI
|
||||
val actualHierarchy = rootURI.toExpectation(hierarchyBuilder)
|
||||
assertEquals(expectedHierarchy, actualHierarchy)
|
||||
}
|
||||
|
||||
protected def ResourceSet createResourceSet(extension HierarchyBuilderTestConfiguration configuration) {
|
||||
val resourceSet = resourceSetProvider.get
|
||||
for (model : models) {
|
||||
val resource = resourceSet.createResource(URI.createURI(model.key))
|
||||
resource.load(new LazyStringInputStream(model.value, 'UTF-8'), null)
|
||||
resource.assertNoIssues
|
||||
}
|
||||
return resourceSet
|
||||
}
|
||||
|
||||
protected def <T extends AbstractHierarchyBuilder> T configureBuilderWith(
|
||||
T hierarchyBuilder,
|
||||
ResourceSet resourceSet
|
||||
) {
|
||||
hierarchyBuilder.resourceAccess = new SimpleLocalResourceAccess(resourceSet)
|
||||
hierarchyBuilder.indexData = resourceDescriptionsProvider.getResourceDescriptions(resourceSet)
|
||||
return hierarchyBuilder
|
||||
}
|
||||
|
||||
protected def String toExpectation(URI rootURI, HierarchyBuilder builder) '''
|
||||
«FOR root : builder.buildRoots(rootURI, null)»
|
||||
«root.toExpectation(builder)»
|
||||
«ENDFOR»
|
||||
'''
|
||||
|
||||
protected def String toExpectation(HierarchyNode node, HierarchyBuilder builder) '''
|
||||
«node.element» {
|
||||
«node.internalToExpectation(builder)»
|
||||
}
|
||||
'''
|
||||
|
||||
protected def String internalToExpectation(HierarchyNode node, HierarchyBuilder builder) '''
|
||||
«FOR location : node.locations»
|
||||
«location.toExpectation»
|
||||
«ENDFOR»
|
||||
«IF node.mayHaveChildren»
|
||||
«FOR childNode : builder.buildChildren(node, null)»
|
||||
«childNode.toExpectation(builder)»
|
||||
«ENDFOR»
|
||||
«ENDIF»
|
||||
'''
|
||||
|
||||
protected def String toExpectation(HierarchyNodeLocation location) {
|
||||
''''«location.text»' [«location.offset», «location.length»]'''
|
||||
}
|
||||
|
||||
@Accessors
|
||||
protected static class HierarchyBuilderTestConfiguration {
|
||||
(ResourceSet)=>HierarchyBuilder hierarchyBuilderProvider
|
||||
Collection<Pair<String, String>> models = newArrayList
|
||||
int index
|
||||
String resourceURI
|
||||
String expectedHierarchy
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -20,7 +20,7 @@ Export-Package: org.eclipse.xtext,
|
|||
org.eclipse.xtext.diagnostics,
|
||||
org.eclipse.xtext.documentation,
|
||||
org.eclipse.xtext.documentation.impl,
|
||||
org.eclipse.xtext.findReferences;x-friends:="org.eclipse.xtext.xbase",
|
||||
org.eclipse.xtext.findReferences,
|
||||
org.eclipse.xtext.formatting,
|
||||
org.eclipse.xtext.formatting.impl,
|
||||
org.eclipse.xtext.formatting2;
|
||||
|
|
|
@ -37,7 +37,7 @@ import com.google.inject.ImplementedBy;
|
|||
* @author Jan Koehnlein - Initial contribution and API in xtext.ui
|
||||
* @author Sebastian Zarnekow - Extracted headless API
|
||||
*
|
||||
* @since 2.7
|
||||
* @since 2.10
|
||||
*/
|
||||
@ImplementedBy(ReferenceFinder.class)
|
||||
public interface IReferenceFinder {
|
||||
|
@ -47,7 +47,7 @@ public interface IReferenceFinder {
|
|||
* shared resource set.
|
||||
*/
|
||||
interface IResourceAccess {
|
||||
<R> R readOnly(URI resourceURI, IUnitOfWork<R, ResourceSet> work);
|
||||
<R> R readOnly(URI targetURI, IUnitOfWork<R, ResourceSet> work);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.findReferences
|
||||
|
||||
import java.util.Map
|
||||
import org.eclipse.emf.common.util.URI
|
||||
import org.eclipse.emf.ecore.EObject
|
||||
import org.eclipse.emf.ecore.EReference
|
||||
import org.eclipse.emf.ecore.resource.Resource
|
||||
import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
|
||||
import org.eclipse.xtext.resource.IReferenceDescription
|
||||
import org.eclipse.xtext.resource.IResourceServiceProvider
|
||||
import org.eclipse.xtext.resource.impl.DefaultReferenceDescription
|
||||
import org.eclipse.xtext.util.IAcceptor
|
||||
|
||||
/**
|
||||
* For local references, populates an {@link IReferenceDescription} that knows its exported container URI.
|
||||
*
|
||||
* @author Sebastian Zarnekow - Initial contribution and API
|
||||
* @author kosyakov - Pulled up to the runtime project
|
||||
*
|
||||
* @since 2.10
|
||||
*/
|
||||
@FinalFieldsConstructor
|
||||
class ReferenceAcceptor implements IReferenceFinder.Acceptor {
|
||||
|
||||
val IResourceServiceProvider.Registry resourceServiceProviderRegistry
|
||||
val IAcceptor<IReferenceDescription> delegate
|
||||
|
||||
Resource currentResource
|
||||
Map<EObject, URI> exportedContainersInCurrentResource
|
||||
|
||||
override void accept(
|
||||
EObject source,
|
||||
URI sourceURI,
|
||||
EReference eReference,
|
||||
int index,
|
||||
EObject targetOrProxy,
|
||||
URI targetURI
|
||||
) {
|
||||
if (currentResource === null || source.eResource() !== currentResource) {
|
||||
computeExportedObjectsMap(source)
|
||||
currentResource = source.eResource()
|
||||
}
|
||||
accept(createReferenceDescription(sourceURI, targetURI, eReference, index, findExportedContainer(source)))
|
||||
}
|
||||
|
||||
protected def void computeExportedObjectsMap(EObject source) {
|
||||
val resource = source.eResource
|
||||
val resourceServiceProvider = resourceServiceProviderRegistry.getResourceServiceProvider(resource.URI)
|
||||
if (resourceServiceProvider !== null) {
|
||||
val resourceDescription = resourceServiceProvider.resourceDescriptionManager.getResourceDescription(resource)
|
||||
exportedContainersInCurrentResource = newHashMap
|
||||
for (description : resourceDescription.exportedObjects) {
|
||||
var instance = description.EObjectOrProxy
|
||||
if (instance.eIsProxy) {
|
||||
instance = resource.getEObject(description.EObjectURI.fragment)
|
||||
}
|
||||
exportedContainersInCurrentResource.put(instance, description.EObjectURI)
|
||||
}
|
||||
} else {
|
||||
exportedContainersInCurrentResource = emptyMap
|
||||
}
|
||||
}
|
||||
|
||||
protected def URI findExportedContainer(EObject obj) {
|
||||
var source = obj
|
||||
if (exportedContainersInCurrentResource.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
var result = exportedContainersInCurrentResource.get(source)
|
||||
while (result === null) {
|
||||
if (exportedContainersInCurrentResource.containsKey(source)) {
|
||||
return result
|
||||
}
|
||||
source = source.eContainer
|
||||
if (source === null) {
|
||||
return null
|
||||
}
|
||||
result = exportedContainersInCurrentResource.get(source)
|
||||
}
|
||||
exportedContainersInCurrentResource.put(source, result)
|
||||
return result
|
||||
}
|
||||
|
||||
override void accept(IReferenceDescription description) {
|
||||
this.delegate.accept(description)
|
||||
}
|
||||
|
||||
protected def IReferenceDescription createReferenceDescription(
|
||||
URI sourceURI,
|
||||
URI targetURI,
|
||||
EReference eReference,
|
||||
int index,
|
||||
URI containerURI
|
||||
) {
|
||||
return new DefaultReferenceDescription(sourceURI, targetURI, eReference, index, containerURI)
|
||||
}
|
||||
}
|
|
@ -34,7 +34,7 @@ import com.google.inject.Singleton;
|
|||
|
||||
/**
|
||||
* @author Sebastian Zarnekow - Initial contribution and API
|
||||
* @since 2.7
|
||||
* @since 2.10
|
||||
*/
|
||||
@Singleton
|
||||
public class ReferenceFinder implements IReferenceFinder {
|
||||
|
|
|
@ -27,6 +27,8 @@ import com.google.inject.Singleton;
|
|||
* targets.
|
||||
*
|
||||
* @author Sebastian Zarnekow - Initial contribution and API
|
||||
*
|
||||
* @since 2.10
|
||||
*/
|
||||
@Singleton
|
||||
public class TargetURICollector {
|
||||
|
|
|
@ -26,7 +26,7 @@ import com.google.common.collect.Sets;
|
|||
* the old APIs.
|
||||
*
|
||||
* @author Sebastian Zarnekow - Initial contribution and API
|
||||
* @since 2.7
|
||||
* @since 2.10
|
||||
*/
|
||||
public class TargetURISet extends AbstractSet<URI> implements TargetURIs {
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ import com.google.inject.ImplementedBy;
|
|||
* a given {@link Key key}.
|
||||
*
|
||||
* @author Sebastian Zarnekow - Initial contribution and API
|
||||
* @since 2.7
|
||||
* @since 2.10
|
||||
*/
|
||||
@ImplementedBy(TargetURISet.class)
|
||||
public interface TargetURIs extends Iterable<URI> {
|
||||
|
|
Loading…
Reference in a new issue