mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[IDE] Introduce semantic annotation functionality and test.
Swift SVN r8618
This commit is contained in:
54
include/swift/IDE/SemanticSourceEntity.h
Normal file
54
include/swift/IDE/SemanticSourceEntity.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
//===- SemanticSourceEntity.h - Routines for semantic source info ---------===//
|
||||||
|
//
|
||||||
|
// This source file is part of the Swift.org open source project
|
||||||
|
//
|
||||||
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
||||||
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||||
|
//
|
||||||
|
// See http://swift.org/LICENSE.txt for license information
|
||||||
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef SWIFT_IDE_SEMANTIC_SOURCE_ENTITY_H
|
||||||
|
#define SWIFT_IDE_SEMANTIC_SOURCE_ENTITY_H
|
||||||
|
|
||||||
|
#include "swift/Basic/SourceLoc.h"
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
namespace swift {
|
||||||
|
class Decl;
|
||||||
|
class ValueDecl;
|
||||||
|
|
||||||
|
namespace ide {
|
||||||
|
|
||||||
|
struct SemanticSourceEntity {
|
||||||
|
CharSourceRange Range;
|
||||||
|
ValueDecl *Dcl;
|
||||||
|
bool IsRef;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// A function receiving SemanticSourceEntity objects.
|
||||||
|
/// \returns true to continue receiving the next object, false to stop.
|
||||||
|
typedef std::function<bool(SemanticSourceEntity AnnoTok)>
|
||||||
|
SemanticEntityReceiverFn;
|
||||||
|
|
||||||
|
/// Walks the provided declarations and passes SemanticSourceEntities to the
|
||||||
|
/// \c Receiver.
|
||||||
|
///
|
||||||
|
/// The entities are given in source-order, as long as the \c Decls array is
|
||||||
|
/// already in source-order.
|
||||||
|
///
|
||||||
|
/// \param Decls the array of declarations to traverse.
|
||||||
|
///
|
||||||
|
/// \param Receiver the function receiving the entities.
|
||||||
|
///
|
||||||
|
/// \returns true if all the entities were passed to the receiver, false if
|
||||||
|
/// the receiver stopped by returning false.
|
||||||
|
bool findSemanticSourceEntities(ArrayRef<Decl*> Decls,
|
||||||
|
SemanticEntityReceiverFn Receiver);
|
||||||
|
|
||||||
|
} // namespace ide
|
||||||
|
} // namespace swift
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
add_swift_library(swiftIDE
|
add_swift_library(swiftIDE
|
||||||
CodeCompletion.cpp
|
CodeCompletion.cpp
|
||||||
REPLCodeCompletion.cpp
|
REPLCodeCompletion.cpp
|
||||||
|
SemanticSourceEntity.cpp
|
||||||
SyntaxColoring.cpp
|
SyntaxColoring.cpp
|
||||||
DEPENDS swiftAST swiftParse swiftSema swiftClangImporter)
|
DEPENDS swiftAST swiftParse swiftSema swiftClangImporter)
|
||||||
|
|
||||||
|
|||||||
134
lib/IDE/SemanticSourceEntity.cpp
Normal file
134
lib/IDE/SemanticSourceEntity.cpp
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
//===- SemanticSourceEntity.cpp - Routines for semantic source info -------===//
|
||||||
|
//
|
||||||
|
// This source file is part of the Swift.org open source project
|
||||||
|
//
|
||||||
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
||||||
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||||
|
//
|
||||||
|
// See http://swift.org/LICENSE.txt for license information
|
||||||
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "swift/IDE/SemanticSourceEntity.h"
|
||||||
|
#include "swift/AST/ASTWalker.h"
|
||||||
|
#include "swift/AST/Decl.h"
|
||||||
|
#include "swift/AST/Expr.h"
|
||||||
|
#include "swift/AST/TypeRepr.h"
|
||||||
|
#include "swift/AST/Types.h"
|
||||||
|
|
||||||
|
using namespace swift;
|
||||||
|
using namespace ide;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class SemaAnnotator : public ASTWalker {
|
||||||
|
SemanticEntityReceiverFn Receiver;
|
||||||
|
bool Cancelled = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SemaAnnotator(SemanticEntityReceiverFn Receiver)
|
||||||
|
: Receiver(std::move(Receiver)) { }
|
||||||
|
|
||||||
|
bool isDone() const { return Cancelled; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool walkToDeclPre(Decl *D) override;
|
||||||
|
std::pair<bool, Expr *> walkToExprPre(Expr *E) override;
|
||||||
|
bool walkToTypeReprPre(TypeRepr *T) override;
|
||||||
|
|
||||||
|
bool walkToDeclPost(Decl *D) override;
|
||||||
|
bool walkToTypeReprPost(TypeRepr *T) override;
|
||||||
|
|
||||||
|
bool passToReceiver(ValueDecl *D, SourceLoc Loc, bool IsRef);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SemaAnnotator::walkToDeclPre(Decl *D) {
|
||||||
|
if (D->isImplicit())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
|
||||||
|
return passToReceiver(VD, VD->getNameLoc(), /*IsRef=*/false);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SemaAnnotator::walkToDeclPost(Decl *D) {
|
||||||
|
if (isDone())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<bool, Expr *> SemaAnnotator::walkToExprPre(Expr *E) {
|
||||||
|
if (isDone())
|
||||||
|
return { false, nullptr };
|
||||||
|
|
||||||
|
if (E->isImplicit())
|
||||||
|
return { true, E };
|
||||||
|
|
||||||
|
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
|
||||||
|
if (!passToReceiver(DRE->getDecl(), E->getLoc(), /*IsRef=*/true))
|
||||||
|
return { false, nullptr };
|
||||||
|
} else if (MemberRefExpr *MRE = dyn_cast<MemberRefExpr>(E)) {
|
||||||
|
if (!passToReceiver(MRE->getMember().getDecl(), E->getLoc(), /*IsRef=*/true))
|
||||||
|
return { false, nullptr };
|
||||||
|
|
||||||
|
} else if (BinaryExpr *BinE = dyn_cast<BinaryExpr>(E)) {
|
||||||
|
// Visit in source order.
|
||||||
|
BinE->getArg()->getElement(0)->walk(*this);
|
||||||
|
BinE->getFn()->walk(*this);
|
||||||
|
BinE->getArg()->getElement(1)->walk(*this);
|
||||||
|
|
||||||
|
// We already visited the children.
|
||||||
|
return { false, E };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { true, E };
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SemaAnnotator::walkToTypeReprPre(TypeRepr *T) {
|
||||||
|
if (IdentTypeRepr *IdT = dyn_cast<IdentTypeRepr>(T)) {
|
||||||
|
for (auto &Comp : IdT->Components) {
|
||||||
|
if (ValueDecl *VD = Comp.getBoundDecl())
|
||||||
|
return passToReceiver(VD, Comp.getIdLoc(), /*IsRef=*/true);
|
||||||
|
if (Type Ty = Comp.getBoundType()) {
|
||||||
|
if (NameAliasType *NAT = dyn_cast<NameAliasType>(Ty.getPointer())) {
|
||||||
|
return passToReceiver(NAT->getDecl(), Comp.getIdLoc(),/*IsRef=*/true);
|
||||||
|
} else if (NominalTypeDecl *NTD = Ty->getAnyNominal()) {
|
||||||
|
return passToReceiver(NTD, Comp.getIdLoc(), /*IsRef=*/true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SemaAnnotator::walkToTypeReprPost(TypeRepr *T) {
|
||||||
|
if (isDone())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SemaAnnotator::passToReceiver(ValueDecl *D, SourceLoc Loc, bool IsRef) {
|
||||||
|
CharSourceRange Range = CharSourceRange(Loc, D->getName().getLength());
|
||||||
|
bool Continue = Receiver({ Range, D, IsRef });
|
||||||
|
if (!Continue)
|
||||||
|
Cancelled = true;
|
||||||
|
return Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ide::findSemanticSourceEntities(
|
||||||
|
ArrayRef<Decl*> Decls,
|
||||||
|
std::function<bool(SemanticSourceEntity AnnoTok)> Receiver) {
|
||||||
|
|
||||||
|
SemaAnnotator Annotator(Receiver);
|
||||||
|
for (Decl *D : Decls) {
|
||||||
|
D->walk(Annotator);
|
||||||
|
if (Annotator.isDone())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
63
test/IDE/annotation.swift
Normal file
63
test/IDE/annotation.swift
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
// RUN: %swift-ide-test -annotate -source-filename %s | FileCheck %s
|
||||||
|
|
||||||
|
// CHECK: struct <Struct>S</Struct> {
|
||||||
|
// CHECK: var <Var>x</Var> : <TypeAlias@>Int</TypeAlias>
|
||||||
|
// CHECK: var <Var>y</Var> : swift.<TypeAlias@>Int</TypeAlias>
|
||||||
|
// CHECK: }
|
||||||
|
struct S {
|
||||||
|
var x : Int
|
||||||
|
var y : swift.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK: class <Class>MyCls</Class> {
|
||||||
|
// CHECK: var <Var>www</Var> : <TypeAlias@>Int</TypeAlias>
|
||||||
|
// CHECK: func <Func>foo</Func>(x : <TypeAlias@>Int</TypeAlias>) {}
|
||||||
|
// CHECK: }
|
||||||
|
class MyCls {
|
||||||
|
var www : Int
|
||||||
|
func foo(x : Int) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK: func <Func>foo</Func>(n : <TypeAlias@>Float</TypeAlias>) -> <TypeAlias@>Int</TypeAlias> {
|
||||||
|
// CHECK: var <Var>q</Var> = MyCls<Constructor@[[@LINE-6]]:7>()
|
||||||
|
// CHECK: </Constructor> var <Var>ee</Var> = "yoo";
|
||||||
|
// CHECK: return 100009
|
||||||
|
// CHECK: }
|
||||||
|
func foo(n : Float) -> Int {
|
||||||
|
var q = MyCls()
|
||||||
|
var ee = "yoo";
|
||||||
|
return 100009
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK: protocol <Protocol>Prot</Protocol> {
|
||||||
|
// CHECK: typealias <AssociatedType>Blarg</AssociatedType>
|
||||||
|
// CHECK: func <Func>protMeth</Func>(x: <TypeAlias@>Int</TypeAlias>)
|
||||||
|
// CHECK: }
|
||||||
|
protocol Prot {
|
||||||
|
typealias Blarg
|
||||||
|
func protMeth(x: Int)
|
||||||
|
}
|
||||||
|
// CHECK: protocol <Protocol>Prot2</Protocol> {}
|
||||||
|
protocol Prot2 {}
|
||||||
|
|
||||||
|
// CHECK: class <Class>SubCls</Class> : <Class@[[@LINE-27]]:7>MyCls</Class>, <Protocol@[[@LINE-7]]:10>Prot</Protocol> {
|
||||||
|
// CHECK: typealias <TypeAlias>Blarg</TypeAlias> = Prot2
|
||||||
|
// CHECK: func <Func>protMeth</Func>(x: <TypeAlias@>Int</TypeAlias>) {}
|
||||||
|
// CHECK: }
|
||||||
|
class SubCls : MyCls, Prot {
|
||||||
|
typealias Blarg = Prot2
|
||||||
|
func protMeth(x: Int) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK: func <Func>genFn</Func><T : Prot where T.Blarg : Prot2>(p : T) -> <TypeAlias@>Int</TypeAlias> {}
|
||||||
|
func genFn<T : Prot where T.Blarg : Prot2>(p : T) -> Int {}
|
||||||
|
|
||||||
|
// FIXME: Constructors.
|
||||||
|
func test(x: Int) {
|
||||||
|
genFn(SubCls())
|
||||||
|
"This is string \(genFn({(a:Int) in SubCls()}(x))) interpolation"
|
||||||
|
}
|
||||||
|
|
||||||
|
func bar(x: Int) -> (Int, Float) {
|
||||||
|
foo(Float())
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user