Scoping Tips and Tricks

26
SCOPING TIPS & TRICKS SEBASTIAN ZARNEKOW

Transcript of Scoping Tips and Tricks

SCOPING TIPS & TRICKSSEBASTIAN ZARNEKOW

IN COMPUTER PROGRAMMING, THE SCOPE OF A NAME BINDING – AN ASSOCIATION OF A NAME TO AN ENTITY, SUCH AS A VARIABLE – IS THE PART OF A COMPUTER PROGRAM WHERE THE BINDING IS VALID: WHERE THE NAME CAN BE USED TO REFER TO THE ENTITY. IN OTHER PARTS OF THE PROGRAM THE NAME MAY REFER TO A DIFFERENT ENTITY (IT MAY HAVE A DIFFERENT BINDING), OR TO NOTHING AT ALL (IT MAY BE UNBOUND). THE SCOPE OF A BINDING IS ALSO KNOWN AS THE VISIBILITY OF AN ENTITY, PARTICULARLY IN OLDER OR MORE TECHNICAL LITERATURE – THIS IS FROM THE PERSPECTIVE OF THE REFERENCED ENTITY, NOT THE REFERENCING NAME. [..] THE TERM "SCOPE" IS ALSO USED TO REFER TO THE SET OF ALL ENTITIES THAT ARE VISIBLE OR NAMES THAT ARE VALID WITHIN A PORTION OF THE PROGRAM OR AT A GIVEN POINT IN A PROGRAM, WHICH IS MORE CORRECTLY REFERRED TO AS CONTEXT OR ENVIRONMENT.

http://en.wikipedia.org/wiki/Scope_%28computer_science%29

IN COMPUTER PROGRAMMING, THE SCOPE OF A NAME BINDING – AN ASSOCIATION OF A NAME TO AN ENTITY, SUCH AS A VARIABLE – IS THE PART OF A COMPUTER PROGRAM WHERE THE BINDING IS VALID: WHERE THE NAME CAN BE USED TO REFER TO THE ENTITY. IN OTHER PARTS OF THE PROGRAM THE NAME MAY REFER TO A DIFFERENT ENTITY (IT MAY HAVE A DIFFERENT BINDING), OR TO NOTHING AT ALL (IT MAY BE UNBOUND). THE SCOPE OF A BINDING IS ALSO KNOWN AS THE VISIBILITY OF AN ENTITY, PARTICULARLY IN OLDER OR MORE TECHNICAL LITERATURE – THIS IS FROM THE PERSPECTIVE OF THE REFERENCED ENTITY, NOT THE REFERENCING NAME. [..] THE TERM "SCOPE" IS ALSO USED TO REFER TO THE SET OF ALL ENTITIES THAT ARE VISIBLE OR NAMES THAT ARE VALID WITHIN A PORTION OF THE PROGRAM OR AT A GIVEN POINT IN A PROGRAM, WHICH IS MORE CORRECTLY REFERRED TO AS CONTEXT OR ENVIRONMENT.

http://en.wikipedia.org/wiki/Scope_%28computer_science%29

IScope and its Clients

Linking:getSingleElement(QualifiedName)

ContentAssist:getAllElements()

Serialization:getElements(EObject)

IScope DisassembledMultimap-like Structure

Two Different Keys

Multimap<QualifiedName, IEObjectDescription>

Multimap<EObject, IEObjectDescription>

Typically Stacked

Shadowing Semantics

Multimaps from FOP View

Multimap<K, V>

~= Map<K, Collection<V>>

~= get(K): Collection<V>

~= (K) -> V*

IScope from FOP View

{ (QualifiedName) -> IEObjectDescription*, (EObject) -> IEObjectDescription* () -> IEObjectDescription*}

IEObjectDescription

{ Name, QualifiedName, URI, String* }

#getEObjectOrProxy

IScopeProvidergetScope(EObject ctx, EReference ref):IScope

EObject ctx

Linking: Owner of Reference

Content Assist: Best Known Container

EReference ref

Reflective representation, e.g. TYPE__SUPER_TYPE for Type.getSuperType()

PUTTING IT TOGETHER

Embrace (QN)->IEODDecorate the Produced Scope, e.greturn new SimpleScope(orig) {..}

Override #getSingleElement(QualifiedName)

Decorate the IEObjectDescriptionreturn new AliasedEObjectDescription {..}

Perform Side-Effect on #getEObjectOrProxy

Validation Meets Scoping

Don’t Limit Content of Scope ‘Arbitrarily’

Include Potentially Invalid Descriptions

Improve User Experience (Navigation, Error Messages)

Add Error or Warning, if Description is Invalidctx.eResource().getErrors().add(..)

Validation Meets Scopingpublic class ErrorAddingDescription extends AliasedEObjectDescription { ErrorAddingDescription(EObject ctx, IEObjectDescription desc) {..} @Override public EObject getEObjectOrProxy() { ctx.eResource().getErrors().add( new EObjectDiagnosticImpl(..)) return super.getEObjectOrProxy(); } }

Detect Unused Locals

Mark Local Declarations as Unused

Local Vars

Import Declarations

Potentially Expensive Validation

Install EMF Adapter on Used Instances

public class MarkAsUsedDescription extends AliasedEObjectDescription { MarkAsUsedDescription(EObject ctx, IEObjectDescription desc) { .. } @Override public EObject getEObjectOrProxy() { EObject result = super.getEObjectOrProxy(); if (result.eResource() == ctx.eResource()) UsageMarkerAdapter.markAsUsed(result); return result; } }

Detect Unused Locals

@Checkpublic void markAsUnused(LocalVar var) { if (UsageMarkerAdapter.isUnused(var)) { addWarning(var, ..) } }

Detect Unused Locals

Avoid Follow-up Errors

Encountered EMF Proxy During getScope(..)

Often Follow-Up Error Situation

Return Scope with Dummy Description

Don’t Produce Unnecessary Errors

Avoid Subsequent Resolution Attempts

public class ErrorScope implements IScope { ErrorScope(EObject ctx, EReference ref) { .. } public IEObjectDescription getSingleElement( QualifiedName name) { return new ErrorDescription(name, ctx, ref); } .. }

Avoid Follow-up Errors

Avoid Follow-up Errorspublic class ErrorDescription extends AliasedEObjectDescription { ErrorDescription(QualifiedName name, EObject ctx, EReference ref) { .. } @Override public EObject getEObjectOrProxy() { return (EObject) ctx.eGet(ref, false); // simplified } }

Dynamic Scopes

Dynamic Languages Allow to Refer Anything

Returns Dynamic Description if Name is Unknown

Record Obtained Descriptions for Later Reuse

Special Case of ErrorScope

COMMON PITFALLS

This is not the context you’re looking forgetScope(EObject ctx, EReference ref)

Content Assist Works on Invalid Documents

Parser Produces Trees rather than a Forest

Best Effort Context Computation

Beware of ClassCastException in getScope(..)

Don’t Enumerate the WorldAvoid eResource().getResourceSet()

and eAllContents()

Embrace the Defaults

Index Queries

Local Resource Contents is Indexed & Cached

Cache Scopes if Necessary (e.g. MapBasedScope)

!

Get Rid of Reflective API

Extendo.e.x.s.impl.DelegatingScopeProvider

Implement #getScope(..) based on EReferenceif (ref == MyDslPackage.Literals…)

Generally Faster & Easier to Debug

Avoid Loading the WorldPut Necessary Information Into Index

User Data Makes Great Filter-Criteria

Index Objects with Aliases / Multiple Names

Use AliasedEObjectDescription for Local Synonyms

If you invoke getEObjectOrProxy() you’re doing it wrong. Usually.

Q & A