-
-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #230 from TypeFox/dh/yang-processor
yang tool progress
- Loading branch information
Showing
32 changed files
with
14,359 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,18 @@ | ||
arguments= | ||
auto.sync=false | ||
build.scans.enabled=false | ||
connection.arguments= | ||
connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER) | ||
connection.gradle.user.home=null | ||
connection.java.home=null | ||
connection.jvm.arguments= | ||
connection.project.dir= | ||
eclipse.preferences.version=1 | ||
gradle.user.home= | ||
java.home= | ||
jvm.arguments= | ||
offline.mode=false | ||
override.workspace.settings=false | ||
project.path=\: | ||
show.console.view=false | ||
show.executions.view=false |
2 changes: 2 additions & 0 deletions
2
yang-lsp/io.typefox.yang.diagram/.settings/org.eclipse.core.resources.prefs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
eclipse.preferences.version=1 | ||
encoding/<project>=UTF-8 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
88 changes: 88 additions & 0 deletions
88
yang-lsp/io.typefox.yang/src/main/java/io/typefox/yang/processor/DataTreeSerializer.xtend
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package io.typefox.yang.processor | ||
|
||
import io.typefox.yang.processor.ProcessedDataTree.AccessKind | ||
import io.typefox.yang.processor.ProcessedDataTree.ElementData | ||
import io.typefox.yang.processor.ProcessedDataTree.HasStatements | ||
import io.typefox.yang.processor.ProcessedDataTree.ListData | ||
import io.typefox.yang.processor.ProcessedDataTree.ModuleData | ||
import java.util.List | ||
import io.typefox.yang.processor.ProcessedDataTree.ElementKind | ||
|
||
class DataTreeSerializer { | ||
|
||
def CharSequence serialize(ModuleData moduleData) { | ||
''' | ||
module: «moduleData.simpleName» | ||
«FOR child : moduleData.children?:#[]» | ||
«doSerialize(child, '', needsConnect(child, moduleData.children))» | ||
«ENDFOR» | ||
rpcs: | ||
«FOR rpc : moduleData.rpcs?:#[]» | ||
«doSerialize(rpc, '', needsConnect(rpc, moduleData.rpcs))» | ||
«ENDFOR» | ||
''' | ||
} | ||
|
||
dispatch def CharSequence doSerialize(HasStatements ele, String indent, boolean needsConnect) { | ||
'''«indent» unsupported data type!''' | ||
} | ||
|
||
dispatch def CharSequence doSerialize(ElementData ele, String indent, boolean needsConnect) { | ||
var accessString = " " | ||
if(ele.getAccessKind() != AccessKind.not_set) { | ||
accessString = ele.getAccessKind().name | ||
} | ||
val prefix = switch (ele.elementKind) { | ||
case Case: | ||
'--:' | ||
default: { | ||
'''«"----".substring(accessString.length)»«!accessString.trim.empty?accessString» ''' | ||
} | ||
} | ||
val label = switch (ele.elementKind) { | ||
case Choice, | ||
case Case: '''(«ele.name»)''' | ||
default: { | ||
ele.name | ||
} | ||
} | ||
val keys = if (ele instanceof ListData) { | ||
ele.keys.empty ? null : ''' [«ele.keys.join(', ')»]''' | ||
} | ||
|
||
val type = ele.getType | ||
// no idea why this indentation is needed in pyang | ||
val additionalIdent = if(ele.elementKind === ElementKind.Choice && prevSibling(ele)?.elementKind === ElementKind.Container) ' ' else '' | ||
''' | ||
«indent»«additionalIdent»+«prefix»«label»«ele.cardinality?.toString()»«keys»«IF type !== null» «type»«ENDIF»«IF ele.featureConditions !== null» {«ele.featureConditions.join(',')»}?«ENDIF» | ||
«IF ele.children !== null» | ||
«FOR child : ele.children» | ||
«doSerialize(child, indent + (needsConnect?'| ':' '), needsConnect(child, ele.children))» | ||
«ENDFOR» | ||
«ENDIF» | ||
''' | ||
} | ||
|
||
private def ElementData prevSibling(ElementData ele) { | ||
val siblings = ele.parent?.children | ||
if(siblings === null) { | ||
return null | ||
} | ||
val eleIdx = siblings.indexOf(ele) | ||
if(eleIdx > 0) { | ||
val prevChild = siblings.get(eleIdx - 1) | ||
if(prevChild instanceof ElementData) { | ||
return prevChild | ||
} | ||
} | ||
} | ||
|
||
private def boolean needsConnect(HasStatements ele, List<HasStatements> siblings) { | ||
if (siblings === null || siblings.last === ele) { | ||
return false | ||
} | ||
return true | ||
} | ||
|
||
} |
53 changes: 53 additions & 0 deletions
53
...lsp/io.typefox.yang/src/main/java/io/typefox/yang/processor/FeatureEvaluationContext.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package io.typefox.yang.processor; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Set; | ||
|
||
import com.google.common.collect.Maps; | ||
import com.google.common.collect.Sets; | ||
|
||
import io.typefox.yang.processor.ProcessedDataTree.ElementIdentifier; | ||
import io.typefox.yang.yang.Feature; | ||
|
||
public class FeatureEvaluationContext { | ||
|
||
private Map<String, Boolean> cache = Maps.newHashMap(); | ||
|
||
private Set<String> include = Sets.newHashSet(), exclude = Sets.newHashSet(); | ||
|
||
public FeatureEvaluationContext(List<String> includedFeatures, List<String> excludedFeatures) { | ||
include.addAll(includedFeatures); | ||
exclude.addAll(excludedFeatures); | ||
} | ||
|
||
public boolean isActive(Feature feature) { | ||
ElementIdentifier featureModule = ProcessorUtility.moduleIdentifier(feature); | ||
var featureQName = featureGlobalQName(featureModule, feature.getName()); | ||
if (cache.containsKey(featureQName)) { | ||
return cache.get(featureQName); | ||
} | ||
var active = isActive(featureModule.name + ":", featureQName) && featureIfConditionsActive(feature); | ||
cache.put(featureQName, active); | ||
return active; | ||
} | ||
|
||
private boolean featureIfConditionsActive(Feature feature) { | ||
return ProcessorUtility.checkIfFeatures(ProcessorUtility.findIfFeatures(feature), this); | ||
} | ||
|
||
private boolean isActive(String modulePrefix, String featureQName) { | ||
// include <module>: means include none of <module> features. | ||
if(include.contains(modulePrefix) && !include.contains(featureQName)) { | ||
// include e.g. 'example-system-ext:' means any of example-system-ext module features should be included | ||
return false; | ||
} | ||
return (include.isEmpty() || include.contains(featureQName) | ||
|| !include.contains(modulePrefix)) // if <module>: not listed in include, all features are enabled | ||
&& (exclude.isEmpty() || !(exclude.contains(featureQName) || exclude.contains(modulePrefix))); | ||
} | ||
|
||
private String featureGlobalQName(ElementIdentifier module, String featureName) { | ||
return module.name + ":" + featureName; | ||
} | ||
} |
107 changes: 107 additions & 0 deletions
107
yang-lsp/io.typefox.yang/src/main/java/io/typefox/yang/processor/FeatureExpressions.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
package io.typefox.yang.processor; | ||
|
||
import org.eclipse.xtext.nodemodel.util.NodeModelUtils; | ||
|
||
import io.typefox.yang.processor.ProcessedDataTree.ElementIdentifier; | ||
import io.typefox.yang.yang.BinaryOperation; | ||
import io.typefox.yang.yang.Expression; | ||
import io.typefox.yang.yang.Feature; | ||
import io.typefox.yang.yang.FeatureReference; | ||
import io.typefox.yang.yang.UnaryOperation; | ||
|
||
public class FeatureExpressions { | ||
|
||
public static abstract class FeatureCondition { | ||
|
||
abstract boolean evaluate(FeatureEvaluationContext ctx); | ||
|
||
public static FeatureCondition create(Expression exp) { | ||
return build(exp); | ||
} | ||
|
||
private static FeatureCondition build(Expression exp) { | ||
if (exp instanceof FeatureReference) { | ||
return new IsFeatureCondition((FeatureReference) exp, ProcessorUtility.moduleIdentifier(exp)); | ||
} else if (exp instanceof UnaryOperation) { | ||
return new IsFeatureCondition((FeatureReference) exp, true, ProcessorUtility.moduleIdentifier(exp)); | ||
} else if (exp instanceof BinaryOperation) { | ||
BinaryOperation bin = (BinaryOperation) exp; | ||
return new BinaryFeatureCondition(build(bin.getLeft()), build(bin.getRight()), | ||
"and".equals(bin.getOperator())); | ||
} | ||
return null; | ||
} | ||
} | ||
|
||
public static class IsFeatureCondition extends FeatureCondition { | ||
|
||
final private Feature feature; | ||
final private boolean not; | ||
final private ElementIdentifier conditionModule; | ||
final private String text; | ||
|
||
public IsFeatureCondition(FeatureReference featureRef, ElementIdentifier conditionModule) { | ||
this(featureRef, false, conditionModule); | ||
} | ||
|
||
public IsFeatureCondition(FeatureReference featureRef, boolean not, ElementIdentifier conditionModule) { | ||
this.feature = featureRef.getFeature(); | ||
this.text = NodeModelUtils.getTokenText(NodeModelUtils.getNode(featureRef)); | ||
this.conditionModule = conditionModule; | ||
this.not = not; | ||
} | ||
|
||
@Override | ||
boolean evaluate(FeatureEvaluationContext ctx) { | ||
return not ? !ctx.isActive(feature) : ctx.isActive(feature); | ||
} | ||
|
||
private String toStringValue = null; | ||
|
||
@Override | ||
public String toString() { | ||
if (toStringValue == null) { | ||
toStringValue = (not ? "!" : "") + this.text; | ||
} | ||
return toStringValue; | ||
} | ||
} | ||
|
||
public static class BinaryFeatureCondition extends FeatureCondition { | ||
final private FeatureCondition left, right; | ||
final private boolean isAnd; | ||
|
||
/** | ||
* Creates an OR binary condition | ||
* | ||
* @param left | ||
* @param right | ||
*/ | ||
public BinaryFeatureCondition(FeatureCondition left, FeatureCondition right) { | ||
this(left, right, false); | ||
} | ||
|
||
/** | ||
* @param left | ||
* @param right | ||
* @param isAnd <code>true</code> if it's an AND binary condition. Default is | ||
* <code>false</code>: OR | ||
*/ | ||
public BinaryFeatureCondition(FeatureCondition left, FeatureCondition right, boolean isAnd) { | ||
super(); | ||
this.left = left; | ||
this.right = right; | ||
this.isAnd = isAnd; | ||
} | ||
|
||
@Override | ||
boolean evaluate(FeatureEvaluationContext ctx) { | ||
return isAnd ? left.evaluate(ctx) && right.evaluate(ctx) : left.evaluate(ctx) || right.evaluate(ctx); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return left.toString() + (isAnd ? " and " : " or ") + right.toString(); | ||
} | ||
} | ||
} |
Oops, something went wrong.